CRM with CUSTOM STS and ADFS
SO the other day I needed to make the STS (security token service) solution I built work with CRM (customer relations management).
CRM is interesting in that unlike SPS (SharePoint) it does not include an STS its self.
The current documentation indicates that CRM relies on ADFS to be the IdP (identity provider).
There are plenty of articles and blog entries for how to setup Claims with CRM.
This is just to talk about some of the gotchas.
One, if you want to setup CRM to access a custom STS then that STS must provide claims that are required.
- UPN (used email address or if possible a constructed UPN)
- Name (display name, whatever you want to be visible as the user in CRM)
- Primary SID (I've used the Serial of the PKI token, but anything works)
The following is most important.
When you setup Claims Based Authentication, CRM will want actual users that are in the local AD (local or trusted domain). That's right, the first part of the setup ONLY works with AD. So if you are using a custom STS, then pull the above claims from AD directly.
For Internet Facing Claims Based Authentication, the users are not required to be local.
Keep in mind the way CRM is constructed, you can only setup one IdP. This is why when using ADFS you can setup multiple points, with SharePoint you can add trusted providers and have as many as you want. It still all went though the SPS STS and hence SharePoint can OOB provide a login screen (drop down) for users to pick which provider to use.
So that means the Custom STS needs to be able to tell the difference between a local request, or a internet request. Yes you could do that by reply, as to where the URL that is making the request. Although that means you would have to have each CRM URL in a list.
The other way is to look for the REALM parameter, which looks like "urn:federation:authentication:windows". Looking for this will indicate the request is for a local AD set of claims.
Keeping the above in mind, will allow CRM to use your custom STS.
Next problem is if you use ADFS with a custom STS. This is needed (unless you add end points, which is only needed if you plan to do plugin development using the SDK).
The primary thing you need to have in order for the STS work with ADFS for CRM is as follows:
The CRM Relaying party in ADFS will error out with the following: System.IdentityModel.Tokens.SecurityTokenException: The incoming identity did not contain any authentication method claims. It goes on to complain about the authentication type was not included "Password".
This seems to be only an issue for Relaying Parties setup for CRM, not a requirement when setup with regular Claims enabled applications.
To solve this problem, the following claims must be added to the token in the STS.
outputIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, System.DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")));
outputIdentity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, "https://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/password"));
You can view all the possible authentication methods here: https://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.authenticationmethods(v=vs.110).aspx
Seems Password is the only one that works, though maybe more investigation is needed. This will get you past the issue and allow for the custom STS to authenticate and ADFS to pass back to CRM.
Next issue is how do you not show the login page in ADFS asking which IdP to use???
Run the following in PowerShell on the ADFS server:
Set-ADFSRelyingPartyTrust -targetName "display name of relaying party" -claimsprovidername "display name of claims provider trust"
The above will reduce the list and cause (if you only set one) to go directly to the IdP and hence no login screen.
Next time we can talk about making a custom end point that the CRM SDK actually likes. This has been a real PITA so far.