{Dynamics CRM + SAML + ADFS}–Get SAML Token programmatically for your Dynamics On-premise environment configured with claims

As a CRM Consultant we come across myriad of requirements. Of them some are our day-day stuffs. But the ones which puts us in a bit of head scratching and brainstorming are the ones which gives us the maximum satisfaction when completed. And this was one of them.

Our client had configured IFD for their Dynamics CRM 2015 on-premise environment. They had a WebAPI web service to which CRM needed to communicate. After initial discussions with the customer, the idea was to pass the SAML token from Dynamics CRM as one of header values in the web api call. The WebAPI would then parse the SAML token from the header of the request and then read the claims to authenticate the caller and send the response back to CRM.

So first things first. We have to pass the SAML token as one of the header values in the web-api call. How to approach this. Let’s understand the mechanism here. For people who already know this, it’s like a repeat but for readers who are unaware of this, I will try to put it in very simple terms.

  • CRM is configured as a relying party fro ADFS. So CRM will only trust only tokens generated from ADFS
  • User tries to login to Microsoft Dynamics CRM. Since user could not present a valid SAML token to CRM, CRM redirects the user to ADFS login page.
  • User enters the username and password. ADFS has active directory configured as trust store. It takes your userid and password and validates it against the identity provider which is your active directory.
  • IF the credentials are correct, Active directory issues a token which contains the claims for the user. ADFS then converts the claims and puts into the SAML token with the claims which are understood by your Dynamics CRM. The user now sends another request to Dynamics CRM and this time with a valid SAML token. CRM now allows the user login.

Believe me this is explained in a very simple way. However there are whole lot of stuffs that you need to configure for this to take place. If you are interested to know the gory details, you can visit the technet article – https://technet.microsoft.com/en-us/library/dn609803.aspx

Now coming back to our topic. Since our intention is to get the SAML token here, if we take an analogy, we have to replicate the whole process as above but without user intervention. Wait? What is the problem then? The problem the user’s credentials which needs to be passed to get the SAML token. How can we do this then?

The solution is to use execution users credentials and to do that we have to replicate the sign-in process. To do that the first thing make the user hit the SignOn page of ADFS.

The signon page has the url of https://<your adfs server url>/adfs/ls/idpinitiatedsignon.aspx

The next thing we need to do is create a SAML asserting endpoint for your relying party if that is already not present. To do this, follow the below steps

  • Open your ADFS server and then open ADFS Management window and click on relying parties.
image
  • Select the Relying Party trust for your CRM and then right click-> Properties  and go to EndPoints.
image
  • Check if you have SAML Assertion end-point showing up. If not then click on Add and enter a new SAML assertion end-point. Binding as POST and Assertion Endpoint with the same URL as your relying party.

 

image
  • Save and close out the Dialog.

Don’t worry. You ADFS configuration will not go wrong here. The Assertion end-point would work in conjunction with the WS-Federation end-points.

So that’s it you are all done. Now comes the coding part to get the SAML token. Well I have covered your back here. I have put the gory code into a managed solution and all you need to do is download the solution from the below codeplex link and then install it into your organization – https://crmsamlgenerator.codeplex.com/

Once installed, the following is the piece of code which you just need to write to get back your SAML assertion token.

OrganizationRequest samlInvoker = new OrganizationRequest();
samlInvoker.RequestName = “saml_SAMLInvoker”;
samlInvoker.Parameters[“IdpLoginPageUrl”] = “
/adfs/ls/idpinitiatedsignon.aspx”;’>https://<federation server url>/adfs/ls/idpinitiatedsignon.aspx”;
samlInvoker.Parameters[“RelyingPartyUrl”] = “<Relying Party URL>”;

var samlResponse = (OrganizationResponse)proxy.Execute(samlInvoker);

var samlParams = samlResponse.Results;

Console.WriteLine(“SAML Token XML: {0}”, samlParams[“SamlTokenXml”]);

 

As you can see from the code above, all you need to do is invoke an action named “saml_SAMLInvoker” with the parameters I have mentioned before and you get the SAML token in XML format back. You call this from javascript too and get this token.

You can pass this to any any web-api call from javascript or server side call. A sample code for passing the SAML XML token in the header value is illustrated below.

_invokeWebAPI: function (samlToken) {
        var req = new XMLHttpRequest();
        req.open(“GET”, “<your web api query”);
        req.setRequestHeader(“Accept”, “application/json”);
        req.setRequestHeader(“Content-Type”, “application/json; charset=utf-8”);
        req.setRequestHeader(“OData-MaxVersion”, “4.0”);

0;       req.setRequestHeader(“OData-Version”, “4.0”);
        req.setRequestHeader(“SAML”, samlToken);
        req.onreadystatechange = function () {
            if (this.readyState == 4 /* complete */) {
                req.onreadystatechange = null;
                if (this.status == 200) {
                    var discovery = JSON.parse(this.response);
                }
                else {
                    var error = JSON.parse(this.response).error;
                }
            }
        };
        req.send();

In my next article, I have explained how to parse the SAML Assertion token – https://debajmecrm.com/parse-saml-assertion-token-generated-from-dynamics-crm-on-premise-environment-configured-with-claims/

Till then happy CRMing.