Configure CRM 2011 and ADFS 2.0 on a single server on port 443
June 21, 2012 31 Comments
Before I start in with the technical bit, a quick review of some terms, the “problem statement” and the alternative solutions before doing this more awkward setup.
You want to deploy CRM 2011 using an “Internet Facing Deployment” (IFD), which in turn must be configured to use a Secure Token Service (STS) such as Active Directory Federations Services (ADFS). Both CRM and ADFS have to be secured with SSL, ie users will connect to them using https.
I’m not going to cover the same ground as has already been detailed in various places about the basics of doing this configuration. The main document to guide you through this installation process for claims based authentication for IFD is on the Microsoft download page along with the implementation guide here:
Install CRM and ADFS on two different servers
By fair the easiest way to configure this with both services using https on port 443 (and using an appropriate certificate). This does mean you have to make sure two separate servers are both highly available (ie don’t fail). While you can install ADFS on pretty much any other server you may not want to do that and expose those servers to the internet at all (especially not something like a domain controller).
If you don’t have another suitable server do you want the outlay for a new server just for ADFS? (even if it is virtualised to avoid the hardware cost, there is still a cost for software licences, including Windows).
Install CRM and ADFS on the same server but on different ports
It is perfectly possible to configure CRM and ADFS to both run on the same web server on different ports. For this setup my preference would be to put CRM on port 443 so users don’t have to remember to add the port number in their URL, and ADFS on another port such as 444 (although the users will be redirected to ADFS and see the port number in the URL, they don’t have to remember this at all).
To do this you need to make sure to add a Windows Firewall rule to allow 444 in to the server in the first place (or whatever third party software you are using). Configure the default web site to use port 444 before installing ADFS and it should all get set up just fine.
The down side of this configuration can be if your users are likely to be using an internet connection where ‘unusual’ ports are not allowed. So if they visit a customer site and are allowed to use a ‘guest’ wireless connection which only allows them to browse to ports 80 and 443, then they won’t be able to reach ADFS and therefore won’t be able to use CRM. If that matters to you, then read on!
The ‘hard’ way – CRM and ADFS on one server, both on port 443
Imagine you don’t have another server you want to / can install ADFS on, other than the CRM server. But you anticipate times your users will not have access to the internet except on standard ports such as 80 and 443. The only option is to install ADFS on the CRM server and configure both to use port 443 (on different IP addresses of course, otherwise they will totally clash, so do make sure you change the bindings in IIS so each is on a single IP which is configured on your server, not just set to “all unassigned”).
The problem is that many people may tell you this can’t be done, and certainly if you just follow the normal configuration steps you will come unstuck. Also, just to be absolutely clear, I am not suggesting this should be the way you usually configure IFD, only a solution when you have the constraints outlined above. Using two servers or two different ports will almost always be easier to set up and troubleshoot.
(Aside: the discussion below is also useful if you installed ADFS on one port and want to switch it to another. Changing the bindings in IIS is definitely not enough on its own, and uninstalling, reinstalling and reconfiguring ADFS is longwinded and still may leave the wrong port being used a well as the right one, so it may come back to bite you later on.)
The problem is that both CRM and ADFS expect to be able to read information about each other’s configuration from a file called FederationMetadata.xml. CRM finds ADFS just fine, and then you add a relying party trust to ADFS and tell it to read from (for example):
it fails with an error message reading “an error occurred during an attempt to read the federation metadata. Verify that the specified URL or host name is a valid federation metadata endpoint”
The usual test is to then try the URL in a browser instead, but this gives a 503 error “service unavailable”.
You can access CRM at this point using https://internalcrm.mydomain.com (or whatever your server and domain are) but ADFS can’t read the federationmetadata from it. So what is going on?
When you install ADFS it actually reserves certain URLs so that requests to these are directed to the ADFS service before it even gets as far as IIS. This is why changing the bindings in IIS from port 443 to 444 (for example) does not work as expected, as that does not change these reservations.
So, firstly let’s take a look at the reservations and then look at changing these to allow CRM to serve the federation metadata file we need. You need to fire up an elevated command prompt (ie one which gives you local admin rights) to make the changes. Start > type “com” and when you see “Windows Command Processor” in the list of applications, right click and choose “Run As Administrator”. Type:
netsh http show urlacl
You will probably see a whole load of reservations, but there are two in particular that relate to ADFS. Since you will want to copy one of these fairly precisely later on, it will make more sense to redirect the output of this command to a text file where you can read and copy things more easily:
netsh http show urlacl > c:\temp\urlacls.txt
Find the one which contains this string:
and select and copy it to the clipboard (saves a lot of tricksy typing in a minute). This reservation is the one causing the problem, since the “+” character is a wildcard, so it looks for any URL on port 443 which contains FederationMetadata/2007-06/ – just like the CRM URL we provided when setting up a relying party trust earlier. It is this wildcard which makes this request get redirected not to IIS and the CRM web service but to ADFS itself, and it can’t return the data expected.
Notice also that this reservation has nothing to relate it only to a specific IP address, so even if you configure the default web site to use a given IP before installing ADFS, this does not prevent it from hitting this problem.
Fixing the problem
I have been through various hoops in a vain effort to fix this issue on a recent project, following the advice in various articles which might fix things if they are broken – such as this one which will help if your URLrewrite module is actually missing or corrupt, or if your reservations are there but have errors such as invalid SIDs, but does not really help to ‘fix’ something which is working as it was designed, but that design causes a conflict.
So, step 1 – delete it with this command:
netsh http delete urlacl url=https://+:443/FederationMetadata/2007-06/
(Tip: to paste into a command line you can use the mouse to right click > paste or press Alt+Space together to get a menu, then press E, then P to Edit > Paste)
Now you have deleted the reservation which was getting in the way you could continue to configure your relying party trusts, but now CRM won’t be able to reach ADFS federationmetadata when it needs t. So we need to put it back, but in a more specific format so it no longer has a wildcard and therefore does not conflict with CRM. Go back to your text file and find the entry reading something like:
https://+:443/FederationMetadata/2007-06/ user =”NT Service\adfssrv” listen=Yes delegate=Yes SDDL=D:(A;;GA;;;S-1-5-80-2246541234-21801234-3603974321-117615432-975697654)
and edit it to replace that + wildcard with an explicit URL for your ADFS server such as adfs.contoso.com or sts.yourdomain.com, then copy and past it into a command to add a new reservation (DO NOT just copy and paste the example below, partly because the domain won’t be right, and nor will the fictitious account SID):
netsh http add urlacl url=https://adfs.contoso.com:443/FederationMetadata/2007-06/ user ="NT Service\adfssrv" listen=Yes delegate=Yes SDDL=D:(A;;GA;;;S-1-5-80-2246541234-21801234-3603974321-117615432-975697654)
(if you need to change the port number as well, eg from 444 to 443, this is the command you would do that with, but you will also want to change the other ADFS URL as well
So now you can continue to configure your relying party trust, ADFS can get the federationmetadata from CRM without interference and everything should work.
(Tip: you can shorten some of the commands above by typing netsh http on its own to enter that ‘context’, then start all the commands from the ‘verb’ eg show, delete, add.)
Many thanks to Richard L and Malcolm S for their extra ideas and pairs of eyes, and their patience while I figured all this out on a recent upgrade project. I was very pleased to be able to deliver this in the way we wanted to give the end users the best possible experience of their shiny new CRM 2011 system.