Monday, February 14, 2011

How to Set Up AD FS 2.0 to SSO to Salesforce using SAML 2.0

Project:
Set up Microsoft AD FS 2.0 on my Windows 2008 R2 Active Directory to allow my users to authenticate to Salesforce.com using their domain accounts using SAML 2.0. We'll be using Federated Authentication and not delegated authentication which requires you to code your own web service.

Introduction:
On paper, Single Sign-On (SSO) looks fairly simple and very logical and can lull you into a false sense of confidence. In practice, it requires a lot of planning, preparation, and some knowledge of sessions, authentication infrastructure, packet capture, encryption, and sometimes alcohol. If you're more of an administrator and less of a programmer, you'll also notice how closely the lines between the two are blurred when you work with these products. There's a lot of articles out there on using several 3rd party IDPs to SSO to the force.com suite but I had trouble finding stuff for AD FS 2.0

Prerequisites:
A working Active Directory, preferably 2008 or higher.
A server or virtual machine that can run AD FS 2.0, preferably 2008 or higher and joined to your domain.
An active Salesforce.com account. They do recommend using a developer account for the initial setup and testing of SSO.
A valid SSL certificate that's trusted on the Internet. I use a wildcard certificate personally.
A DNS host record for your new AD FS. For this tutorial, I'm using samlportal.example.com
If you're using a firewall (which you should) between your AD FS and the internet, then you'll need to publish inbound SSL to it. Preferably with no authentication required.
If you want to set up a AD FS Proxy in a DMZ, then a second server or virtual machine will be required. For that, you'll need port 443 open from the proxy AD FS to the internal AD FS and 443 open from the internet to your proxy AD FS. The proxy server does NOT have to be domain joined.

Federation Service Name notes:
Try to avoid using your internal DNS AD name, and do not name it the same as the server's host name. You really want this name to be unique. This name will also have to be resolvable on the Internet since you'll need an A record for it and an SSL certificate.

Setup:
First download AD FS 2.0 to your server.
Install the IIS role on your server.
Add your SSL certificate to IIS (IIS manager under Server Certificates) and bind it to 443.
Test the server to make sure SSL is working.
Only AFTER you have the SSL settings right, then proceed to install AD FS 2.0
Install AD FS 2.0 and choose the "Federation Server" option.
Then run the AD FS 2.0 Federation Server Configuration Wizard to Create a new Federation Service.
Now you have a decision point, if you've only got a handful of users you can just do a stand-alone install. If you plan on having hundreds to thousands of users on this, then you can set up a Farm which will allow you to have multiple servers. Note: This option uses Windows Internal database (aka SQL express effectively). If you want to utilize an existing SQL DB server, you have to install using the command line.
Next the installer will detect your SSL certificate. If it doesn't, something's wrong with your IIS configurations.
Click Next
It'll install now and give you a list of success/failures. Warnings are generally not a problem and often occur if you're reinstalling AD FS.
If you get an SPN registration error, you'll have to update it manually from the command line. Substitute the following using your federation id and the account you're running AD FS as a service under.
setspn -S host//samlportal.example.com ADFSserviceAcctName

After that's done, go into the AD FS 2.0 console, click Service, right click on Service and choose Edit Federation Service Properties.


Confirm that the Federation Service name, etc all match what you have on your DNS A record and your SSL certificate. Copy down your Federation Service Identifier.

Then go under Certificates and Export a copy of your Token-signing certificate. Now we'll jump over to Salesforce as we can't proceed without data from them.

Next go into your salesforce account, then Setup, then on the left Security Controls, then Single Sign-On settings. This next bit of configuration came from a forum post from "Da G Man" on the thread: http://social.msdn.microsoft.com/Forums/en/Geneva/thread/2fc66b27-966c-49e5-891e-6e7e404e001d (Yeah, forums are great).

Choose Edit, then change the SAML drop down to 2.0.
For the Issuer, enter in your Federation Service Identifier. In this example, it was http://samlportal.example.com/adfs/services/trust
And yes, that is http and not https. And it is CASE-Senstive.
Choose User ID Type: Assertion contains User's salesforce.com username
Choose User ID Location: User ID is an Attribute element.
Enter Attribute Name: mail
Then click Save.

Now you can click on the Download Metadata button. Copy this file to your AD FS server.

Next on your AD FS server, go to Trust Relationships>Relying Party Trusts and add a new Relying Party Trust.
Under Data Source, choose Import data about the relying party from a file and choose your file that you downloaded from Salesforce.
Name it something. (This name will display on your user's login portal)
Choose the Permit all users option.
Click Next.
Click Finish.
Right-click on the relying party trust and choose Edit Claim Rules.
Name the claim something.
Choose Active Directory for the Attribute Store.
Choose E-mail Addresses for the LDAP Attribute and type in mail for the Outgoing claim Type.

Click OK, then OK.
Now make sure you have a user in salesforce whose username field matches the primary email address of a user in your active directory. Also make sure that this user is not an Administrator in Salesforce as by policy SSO supposedly doesn't work for those.

Now it's time to test. After much searching I figured out what URL I was supposed to use and I've provided it below:

(yes, it is https and it has no bearing on your Federation service identifier being http)


At this point the IDPInitiatedSignOn page should have loaded. If it didn't, then you've got a configuration issue. Otherwise you should be at a page that gives you the option to either log on or log on and go to salesforce in one step.

So now you've (hopefully) got the IDP initiated sign on part working! At some point you'll notice that you're still able to log in with your old login and password if you go to the salesforce site directly. Apparently the only way to fix that is to first switch to using their My Domain feature.



Once you're provisioned your domain, then log off, then back on using your new domain URL which will be in the form of yourdomain.my.salesforce.com

After that's set up, if you go back into Single Sign-On Settings and enter in an Identity Provider Login URL and Save your site will now force all visitors to use Single Sign-On. Now the URL is tricky and I found one that works but I can't promise it's the 'correct' one but it works and that'll do for now.
The above URL is comprised of my my SSO provider's IDP signon page plus a '?" then loginToRp= and then your salesforce domain name.

For further troubleshooting you may want to install a header capture program like Fiddler to help you debug your setup.

Feel free to comment if you have any corrections or suggestions and I'll integrate them into this howto.

Additional Notes:
There's a fun bug in Firefox where it'll prompt you endlessly for credentials. Workaround is here:

If you want to provide the Identity Provider Logout URL you can use:
https://samlportal.example.com/adfs/ls/?wa=wsignout1.0 (yeah, it's a legacy method but seems to work)

Useful Links:

Good forum post that answers the my domain SSO question.







11 comments:

Superpat said...

Great writeup, Gwawgnu! One enhancement - the URL you give for 'Identity Provider Login URL' results in the SP (Salesforce) telling the IdP (AD FS) to do IdP-initiated SAML 2.0. This kinda works, but any RelayState parameter gets lost.

A better value is 'https://samlportal.example.com/adfs/ls/' - this will result in deep links such as https://yourdomain.my.salesforce.com/_ui/core/chatter/ui/ChatterPage being carried through the process and the user ending up at https://na1.salesforce.com/_ui/core/chatter/ui/ChatterPage.

I'll write my experiences up at http://wiki.developerforce.com/ sometime soon. Thanks for the headstart!

Pat Patterson
Force.com Principal Developer Evangelist
Salesforce.com

Gnawgnu said...

Cool, thanks I'll try that one out. I'm still trying to get a handle around all this and I'll look forward to seeing your final wiki entry.

Pradeep Kumar said...

Hi,
I want to that Window server 2008 R2 is necessary for sso or we can use window server 2008 sp2?
Please help me.

Thanks
Pradeep Kumar

Gnawgnu said...

The AD FS 2.0 RTW is supported on a the original windows 2008 server with SP2. http://support.microsoft.com/kb/974408

Pradeep Kumar said...

Hi,

Is it possible to create SSO for the following scenario.

I have standard user in my Test1 org and the same username exist in my test2 org as a customer portal user on authenicated sites.
So i want the test1 standard user can login from test1 org to test2 sites.

Please provide me the best suitable solution.

Thanks in advance
Pradeep Kumar

Gnawgnu said...

I haven't done anything with SAML since February but I think since you're using Email address which would be unique between different domains even if the base username is the same it should be doable. Good luck with that.

Pradeep Kumar said...

Hi Gnawgnu,

I have a problem using adfs server.
when i click on link like https://sample.test.com/adfs/ls/idpinitiatedsignon.aspx?loginToRp=https://saml.salesforce.com
it ask me for the adfs user to login but my need it never ask me to enter username and password.I want adfs user's username and password should be in URl.so it redirect the browser to my sites.
Is there any way to do this?

Thanks in advance
Pradeep Kumar

Gnawgnu said...

The ADFS server ideally should be configured with integrated authentication and your IE browser should have it as a trusted site with the log on with current credentials option listed in the security settings for the trusted zone. The username and password should never be included in the URL, only the encrypted token that's created by the ADFS should be in the URL string. A SAML authentication should never create a scenario where a username or password is stored in a string that goes to the trusting party.

Rob said...

Great write up! Do you know if it will work with Windows Server 2003 SP1 and ADFS 2.0. We wont be ugrading to 2008 for quite a few months

Gnawgnu said...

I think that ADFS 2.0 is only supported on 2008 and above.

Gaurav Gathania said...

Hi Gwawgnu,

Great article and was searching on something for Salesforce setup with ADFS2. We have used the exact same configuration on our ADFS 2 environment now are running into an issues with Salesforce recent changes.

Salesforce latest recommendations are to stop using default proxy certificates for encoding SP initiated SAML authentication request. Salesforce is enforcing this right now for any new Orgs which are on Winter 17 and will gradually roll out for all other orgs by August 7 2017.

We have couple of Salesforce Orgs that are authenticating using a single relying party setup on ADFS 2.0.[ADFS 2 cannot have multiple relying parties for same domain] and with recent recommendation each of Salesforce org has to install its request signing certificate in ADFS.

Can an ADFS relying party have multiple request signing certificates corresponding to each Relying party trust identifiers?