Configure CRM 2011 and ADFS 2.0 on a single server on port 443
June 21, 2012 13 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:
http://www.microsoft.com/download/en/details.aspx?id=3621
and there a various blog posts and a handy YouTube video to show you how easy this all is. You have two main options to set this up fairly easily:
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):
https://auth.mydomain.com/federationmetadata/2007-06/federationmetadata.xml
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?
Reserved URLs
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:
https://+:443/FederationMetadata/2007-06/
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.
Have you tried this with a single IP but using HTTPS host-headers to distinguish between the sites? Curious to know if that can be made to work…
No, I have not tried doing this with host headers since there are already enough DNS names to worry about for internal URL + one per organisation for external access plus ADFS itself. Also not sure what the impact would be on firewall rules simply forwarding everything through to same IP and port, especially with more ‘active’ devices such as TMG. I was trying to come up with a method that can be followed every time (when needed) and reliably work.
You can’t get round the need for separate URLs for all the CRM organisations for external access, as that is how ADFS determines this is an external logon and prompts for user credentials rather than requesting a Kerberos token for SSO which it does for internal access (where the org is determined by the folder on the end of the URL eg crm.internal.com/MyOrg – if none specified it will redirect to user’s default organisation).
Also, if using https then whatever name is used has to match your certificate, so with multiple names it quickly becomes easier, cheaper and more manageable to use a single wildcard certificate (from an external trusted authority rather than self-signed) for all these services (and possibly others, such as SSRS).
I don’t have a problem with the multiple hostnames – after all that’s what aliases are for – but I dislike having server adaptors with multiple IPs because of other problems that can then bring. It’s a personal thing I guess as there are pros and cons with each…
I agree that it’s a pain that wildcards are STILL not supported in hostheaders in IIS. On the certificate side I beleive that a wildcard (or a SAN cert) is **required** to implement hostheaders with https. (Because IIS needs to decrypt the request from the client to figure out what hostname the client was using in the first place).
I guess it’s unlikey that people trying to do this will have lots of CRM organisations to handle so the number of hostheaders should still be reasonably manageable. I’ll add it to my list of things to try one day…
Thanks for your help Adam.
Thanks for your input! It would be interesting to hear back when you have a chance to test this.
I have seen some reports of issues with multiple server IPs in some virtualised environments (usually older versions of hyper-V, from memory), but was able to use this approach with no problems at all in a recent ESX hosted deployment.
As always, keeping it simple will usually result in better availability of the system and ease of maintenance, troubleshooting and so on. Two separate servers for CRM and ADFS is still probably easier for most deployments.
Pingback: Did You Know, Dynamics CRM & xRM #16 « North52
Adam,
I’m new to CRM but after deploying the server I now want to put it online instead of having internal access only.
I need to know if it is mandatory to have multiple SAN certificate or Wildcard to do this or would it also work with one SAN certificate?
thanks
Short answer is no, you need a certificate which has lots of names on or just a wildcard one since there are so many different URLs you are trying to secure at the same time, for the user to access CRM internally eg myserver.mydomain.com/mycrmorg, or CRM externally mycrmorg.mydomain.com (a different URL), and ADFS eg sts.mydomain.com or adfs.mydomain.com, and for ADFS to talk to CRM at auth.mydomain.com and for third party apps or the Outlook client wizard to talk to at crmdev.mydomain.com. Of course you might have multiple organisations too (eg for dev, test, training, live).
So you could use lots of individual certs for each of these but frankly that seems like too much work. A wildcard is always my preference
Hi…I have wild card certificate which is going to expire on 21st nov,2012.So please tell me what are the steps which I have to follow to to update certificate and ADFS 2.0.
1.Does I have to attached renewed certificate again to default website and CRM website.
2.Does I have to add these entry again to MMC for personal and Trusted certificate.
If Not,then do let me know what are the steps that need to perform as still there are 20 days for certificate expiration.
You will have to import and associate the renewed certificate with your sites, and both CRM server and ADFS will need the public key in the personal store so they can encrypt data to be used at the other end.
As a rule of thumb, a certificate which is actually renewed via a renewal request will work more easily than simply buying a new unrelated one which starts from the end of the previous one.
Hi Adam
I felt compelled to write and thank you for this article as I have been pulling my hair out trying to get an ADFS test bed set up for use with a local network SSL wildcard system. I had been going round in circles with creating new sub domains for sites that had originally been created for the default site in IIS 7.5 on 2008, but was constantly getting the 503 Service Unavailable error. What your article helped prove was what the Microsoft uninstall program for ADFS doesn’t do! It fails to remove the reserved URLs from a server it has been originally installed on as I had moved it from the DC to a stand alone server and kept the sites on the DC. The show urlacl list presented me with a list of reservations that were stopping any ADFS traffic that wasn’t under the default site on the DC and once deleted manually using your instructions above everything sprang into life.
Many, many thanks for sharing your wisdom.
Kind regards
Ian
You’re very welcome, glad it helped!
Thanks for this post Adam. It seems that every time I setup a CRM 2011 IFD I run into a new issue (and learn something new). I have now implemented this a dozen times and this week was the first time we had ADFS and CRM (2 IPs) both on 443 on the same server (not ideal). Your post was very helpful.
Cheers
Nick
Nick, I hope it made your life a little easier than the first time I did this and had to figure it out for myself.