For the last few years ObjectSharp has been using Salesforce.com to help manage parts of the business. As business increased, our reliance on Salesforce increased. More and more users started getting added, and as all stories go, these accounts became one more burden to manage.
This is the universal identity problem – too many user accounts for the same person. As such, one of my internal goals here is to simplify identity at ObjectSharp.
While working on another internal project with Salesforce i got to thinking about how it manages users. It turns out Salesforce allows you to set it up as a SAML relying party. ADFS v2 supports being a SAML IdP. Theoretically we have both sides of the puzzle, but how does it work?
Well, first things first. I checked out the security section of the configuration portal:

There was a Single Sign-On section, so I followed that and was given a pretty simple screen:

There isn’t much here to setup. Going down the options, here is what I came up with:
SAML Version
I know from previous experience that ADFS supports version 2 of the SAML Protocol.
Issuer
What is the URI of the IdP, which in this case is going to be ADFS? Within the ADFS MMC snap-in, if you right click the Service node you can access the properties:

In the properties dialog there is a textbox allowing you to change the Federation Service Identifier:

We want that URI.
Within Salesforce we set the Issuer to the identifier URI.
Identity Provider Certificate
Salesforce can’t just go and accept any token. It needs to only be able to accept a token from my organization. Therefore I upload the public key used to sign my tokens from ADFS. You can access that token by going to ADFS and selecting the Certificates node:

Once in there you can select the signing certificate:

Just export the certificate and upload to Salesforce.
Custom Error URL
If the login fails for some reason, what URL should it go to? If you leave it blank, it redirects to a generic Salesforce error page.
SAML User ID Type
This option is asking what information we are giving to Salesforce, so it can correlate that information to one of their internal ID’s. Since for this demo I was just using my email address, I will leave it with Assertion contains User’s salesforce.com username.
SAML User ID Location
This option is asking where the above ID is located within the SAML token. By default it will accept the nameidentifier but I don’t really want to pass my email as a name so I will select user ID is in an Attribute element.
Now I have to specify what claim type the email address is. In this case I will go with the default for ADFS, which is http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress.
On to Active Directory Federation Services
We are about half way done. Now we just need to tell ADFS about Salesforce. It’s surprisingly simple.
Once you’ve saved the Salesforce settings, you are given a button to download the metadata:

Selecting that will let you download an XML document containing metadata about Salesforce as a relying party.
Telling ADFS about a relying party is pretty straightforward, and you can find the detailed steps in a previous post I wrote about halfway through the article.
Once you’ve added the relying party, all you need to do is create a rule that returns the user’s email address as the above claim type:

Everything should be properly configured at this point. Now we need to test it.
When I first started out with ADFS and SAML early last year, I couldn’t figure out how to get ADFS to post the token to a relying party. SAML is not a protocol that I’m very familiar with, so I felt kinda dumb when I realized there is an ADFS URL you need to hit. In this case it’s https://[adfs.fqdn]/adfs/ls/IdpInitiatedSignOn.aspx.
It brings you to a form page to select which application to post a token to:

Select your relying party and then go.
It will POST back to an ADFS endpoint, and then POST the information to the URL within the metadata provided earlier. Once the POST’ing has quieted down, you end up on your Salesforce dashboard:

All in all, it took about 10 minutes to get everything working.