Salesforce.com Single Sign On using ADFS v2

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:

image

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

image

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:

image

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

image

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:

image

Once in there you can select the signing certificate:

image

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:

image

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:

image

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:

image

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:

image

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

Single Sign-On from Active Directory to a Windows Azure Application Whitepaper

Just came across this on Alik Levin's blog.  I just started reading it, but so far so good!  Here is the abstract:

This paper contains step-by-step instructions for using Windows® Identity Foundation, Windows Azure, and Active Directory Federation Services (AD FS) 2.0 for achieving SSO across web applications that are deployed both on premises and in the cloud. Previous knowledge of these products is not required for completing the proof of concept (POC) configuration. This document is meant to be an introductory document, and it ties together examples from each component into a single, end-to-end example.

You can download it here in either docx or pdf: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=1296e52c-d869-4f73-a112-8a37314a1632

Step-by-Step Guide for Federation between Ping Identity PingFederate and ADFS 2.0

Over on the Claims-Based Identity Blog they have a post linking to a step by step guide for creating a federated solution with PingFederate and ADFS 2.

Here is the abstract of the guide:

Building on existing documentation, this step-by-step guide walks you through the setup of a basic lab deployment of AD FS 2.0 and PingFederate that performs cross-product, browser-based identity federation. Both products perform both identity federation roles: claims provider/identity provider and relying party/service provider. This document is intended for developers and system architects who are interested in understanding the basic modes of interoperability between AD FS 2.0 and PingFederate.

You can find the related documents on TechNet at http://technet.microsoft.com/en-us/library/dd727938(WS.10).aspx.

ADFS Content on TechNet Wiki

Over on the Ask the Directory Services Team blog on TechNet they have a good post on a few wiki entries for dealing with ADFS and troubleshooting.

The Basics of Building a Security Token Service

Last week at TechDays in Toronto I ran into a fellow I worked with while I was at Woodbine.  He works with a consulting firm Woodbine uses, and he caught my session on Windows Identity Foundation.  His thoughts were (essentially—paraphrased) that the principle of Claims Authentication was sound and a good idea, however implementing it requires a major investment.  Yes.  Absolutely.  You will essentially be adding a new tier to the application.  Hmm.  I’m not sure if I can get away with that analogy.  It will certainly feel like you are adding a new tier anyway.

What strikes me as the main investment is the Security Token Service.  When you break it down, there are a lot of moving parts in an STS.  In a previous post I asked what it would take to create something similar to ADFS 2.  I said it would be fairly straightforward, and broke down the parts as well as what would be required of them.  I listed:

  • Token Services
  • A Windows Authentication end-point
  • An Attribute store-property-to-claim mapper (maps any LDAP properties to any claim types)
  • An application management tool (MMC snap-in and PowerShell cmdlets)
  • Proxy Services (Allows requests to pass NAT’ed zones)

These aren’t all that hard to develop.  With the exception of the proxy services and token service itself, there’s a good chance we have created something similar to each one if user authentication is part of an application.  We have the authentication endpoint: a login form to do SQL Authentication, or the Windows Authentication Provider for ASP.NET.  We have the attribute store and something like a claims mapper: Active Directory, SQL databases, etc.  We even have an application management tool: anything you used to manage users in the first place.  This certainly doesn’t get us all the way there, but they are good starting points.

Going back to my first point, the STS is probably the biggest investment.  However, it’s kind of trivial to create an STS using WIF.  I say that with a big warning though: an STS is a security system.  Securing such a system is NOT trivial.  Writing your own STS probably isn’t the best way to approach this.  You would probably be better off to use an STS like ADFS.  With that being said it’s good to know what goes into building an STS, and if you really do have the proper resources to develop one, as well as do proper security testing (you probably wouldn’t be reading this article on how to do it in that case…), go for it.

For the sake of simplicity I’ll be going through the Fabrikam Shipping demo code since they did a great job of creating a simple STS.  The fun bits are in the Fabrikam.IPSts project under the Identity folder.  The files we want to look at are CustomSecurityTokenService.cs, CustomSecurityTokenServiceConfiguration.cs, and the default.aspx code file.  I’m not sure I like the term “configuration”, as the way this is built strikes me as factory-ish.

image

The process is pretty simple.  A request is made to default.aspx which passes the request to FederatedPassiveSecurityTokenServiceOperations.ProcessRequest() as well as a newly instantiated CustomSecurityTokenService object by calling CustomSecurityTokenServiceConfiguration.Current.CreateSecurityTokenService().

The configuration class contains configuration data for the STS (hence the name) like the signing certificate, but it also instantiates an instance of the STS using the configuration.  The code for is simple:

namespace Microsoft.Samples.DPE.Fabrikam.IPSts
{
    using Microsoft.IdentityModel.Configuration;
    using Microsoft.IdentityModel.SecurityTokenService;

    internal class CustomSecurityTokenServiceConfiguration
: SecurityTokenServiceConfiguration
    {
        private static CustomSecurityTokenServiceConfiguration current;

        private CustomSecurityTokenServiceConfiguration()
        {
            this.SecurityTokenService = typeof(CustomSecurityTokenService);
            this.SigningCredentials =
new X509SigningCredentials(this.ServiceCertificate);
            this.TokenIssuerName = "https://ipsts.fabrikam.com/";
        }

        public static CustomSecurityTokenServiceConfiguration Current
        {
            get
            {
                if (current == null)
                {
                    current = new CustomSecurityTokenServiceConfiguration();
                }

                return current;
            }
        }
    }
}

It has a base type of SecurityTokenServiceConfiguration and all it does is set the custom type for the new STS, the certificate used for signing, and the issuer name.  It then lets the base class handle the rest.  Then there is the STS itself.  It’s dead simple.  The custom class has a base type of SecurityTokenService and overrides a couple methods.  The important method it overrides is GetOutputClaimsIdentity():

protected override IClaimsIdentity GetOutputClaimsIdentity(
IClaimsPrincipal principal, RequestSecurityToken request, Scope scope)
{
    var inputIdentity = (IClaimsIdentity)principal.Identity;

    Claim name = inputIdentity.Claims.Single(claim =>
claim.ClaimType == ClaimTypes.Name);
    Claim email = new Claim(ClaimTypes.Email,
Membership.Provider.GetUser(name.Value, false).Email);
    string[] roles = Roles.Provider.GetRolesForUser(name.Value);

    var issuedIdentity = new ClaimsIdentity();
    issuedIdentity.Claims.Add(name);
    issuedIdentity.Claims.Add(email);

    foreach (var role in roles)
    {
        var roleClaim = new Claim(ClaimTypes.Role, role);
        issuedIdentity.Claims.Add(roleClaim);
    }

    return issuedIdentity;
}

It gets the authenticated user, grabs all the roles from the RolesProvider, and generates a bunch of claims then returns the identity.  Pretty simple.

At this point you’ve just moved the authentication and Roles stuff away from the application.  Nothing has really changed data-wise.  If you only cared about roles, name, and email you are done.  If you needed something more you could easily add in the logic to grab the values you needed. 

By no means is this production ready, but it is a good basis for how the STS creates claims.

Whitepaper on ADFS 2 Federation with Shibboleth and the InCommon Federation

Over on the Claims-Based Identity blog, they announced a whitepaper was just released on using ADFS 2 to federate with Shibboleth 2 and the InCommon Federation.  I just started reading through it, but it looks really well written.

Here is the abstract of the paper itself:

Through its support for the WS-Federation and Security Assertion Markup Language (SAML) 2.0 protocols, Microsoft® Active Directory® Federation Services 2.0 (AD FS 2.0) provides claims-based, cross-domain, Web single sign-on (SSO) interoperability with non-Microsoft federation solutions. Shibboleth® 2, through its support for SAML 2.0, enables cross-domain, federated SSO between environments that are running Microsoft and Shibboleth 2 federation infrastructures.

You can download the whitepaper in .docx format.

What is Shibboleth?

The Shibboleth System is a standards based, open source software package for web single sign-on across or within organizational boundaries. It allows sites to make informed authorization decisions for individual access of protected online resources in a privacy-preserving manner.

What is InCommon?

InCommon eliminates the need for researchers, students, and educators to maintain multiple passwords and usernames. Online service providers no longer need to maintain user accounts. Identity providers manage the levels of their users' privacy and information exchange. InCommon uses SAML-based authentication and authorization systems (such as Shibboleth®) to enable scalable, trusted collaborations among its community of participants.

Using Claims Based Identities with SharePoint 2010

When SharePoint 2010 was developed, Microsoft took extra care to include support for a claims-based identity model.  There are quite a few benefits to doing it this way, one of which is that it simplifies managing identities across organizational structures.  So lets take a look at adding a Secure Token Service as an Authentication Provider to SharePoint 2010.

First, Some Prerequisites

  • You have to use PowerShell for most of this.  You wouldn’t/shouldn’t be adding too many Providers to SharePoint all that often so there isn’t a GUI for this.
  • The claims that SharePoint will know about must be known during setup.  This isn’t that big a deal, but…

Telling SharePoint about the STS

Once you’ve collected all the information you need, open up PowerShell as an Administrator and add the SharePoint snap-in on the server.

Add-PSSnapin Microsoft.SharePoint.PowerShell

Next we need to create the certificate and claim mapping objects:

$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("d:\path\to\adfsCert.cer")

$claim1 = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" -IncomingClaimTypeDisplayName "Role" –SameAsIncoming

$claim2 = New-SPClaimTypeMapping "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" –SameAsIncoming

There should be three lines.  They will be word-wrapped.

The certificate is pretty straightforward.  It is the public key of the STS.  The claims are also pretty straightforward.  There are two claims: the roles of the identity, and the email address of the identity.  You can add as many as the STS will support.

Next is to define the realm of the Relying Party; i.e. the SharePoint server.

$realm = "urn:" + $env:ComputerName + ":adfs"

By using a URN value you can mitigate future changes to addresses.  This becomes especially useful in an intranet/extranet scenario.

Then we define the sign-in URL for the STS.  In this case, we are using ADFS:

$signinurl = https://[myAdfsServer.fullyqualified.domainname]/adfs/ls/

Mind the SSL.

And finally we put it all together:

New-SPTrustedIdentityTokenIssuer -Name "MyDomainADFS2" -Description "ADFS 2 Federated Server for MyDomain" -Realm $realm -ImportTrustCertificate $cert -ClaimsMappings $claim1,$claim2 -SignInUrl $signinurl -IdentifierClaim $claim2.InputClaimType

This should be a single line, word wrapped.  If you wanted to you could just call New-SPTrustedIdentityTokenIssuer and then fill in the values one at a time.  This might be useful for debugging.

At this point SharePoint now knows about the STS but none of the sites are set up to use it.

Authenticating SharePoint sites using the STS

For a good measure restart SharePoint/IIS.  Go into SharePoint Administration and create a new website and select Claims Based Authentication at the top:

image

Fill out the rest of the details and then when you get to Claims Authentication Types select Trusted Identity Provider and then select your STS.  In this case it is my ADFS Server:

image

Save the site and you are done.  Try navigating to the site and it should redirect you to your STS.  You can then manage users as you would normally with Active Directory accounts.

Claims Transformation and Custom Attribute Stores in Active Directory Federation Services 2

Active Directory Federation Services 2 has an amazing amount of power when it comes to claims transformation.  To understand how it works lets take a look at a set of claims rules and the flow of data from ADFS to the Relying Party:

image

We can have multiple rules to transform claims, and each one takes precedence via an Order:

image

In the case above, Transform Rule 2 transformed the claims that Rule 1 requested from the attribute store, which in this case was Active Directory.  This becomes extremely useful because there are times when some of the data you need to pull out of Active Directory isn’t in a useable format.  There are a couple options to fix this:

  • Make the receiving application deal with it
  • Modify it before sending it off
  • Ignore it

Lets take a look at the second option (imagine an entire blog post on just ignoring it…).  ADFS allows us to transform claims before they are sent off in the token by way of the Claims Rule Language.  It follows the pattern: "If a set of conditions is true, issue one or more claims."  As such, it’s a big Boolean system.  Syntactically, it’s pretty straightforward.

To issue a claim by implicitly passing true:

=> issue(Type = "http://MyAwesomeUri/claims/AwesomeRole", Value = "Awesome Employee");

What that did was ignored the fact that there weren’t any conditions and will always pass a value.

To check a condition:

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role", Value == "SomeRole"]
    => issue(Type = "http://MyAwesomeUri/claims/AwesomeRole", Value = "AwesomeRole");

Breaking down the query, we are checking that a claim created in a previous step has a specific type; in this case role and the claim’s value is SomeRole.  Based on that we are going to append a new claim to the outgoing list with a new type and a new value.

That’s pretty useful in it’s own right, but ADFS can actually go even further by allowing you to pull data out of custom data stores by way of Custom Attribute Stores.  There are four options to choose from when getting data:

  1. Active Directory (default)
  2. LDAP (Any directory that you can query via LDAP)
  3. SQL Server (awesome)
  4. Custom built store via custom .NET assembly

Let’s get some data from a SQL database.  First we need to create the attribute store.  Go to Trust Relationships/Attribute Stores in the ADFS MMC Console (or you could also use PowerShell):

image

Then add an attribute store:

image

All you need is a connection string to the database in question:

image

The next step is to create the query to pull data from the database.  It’s surprisingly straightforward.  This is a bit of a contrived example, but lets grab the certificate name and the certificate hash from a database table where the certificate name is equal to the value of the http://MyCertUri/UserCertName claim type:

c:[type == http://MyCertUri/UserCertName]
   => issue(store = "MyAttributeStore",
         types = ("http://test/CertName", "http://test/CertHash"),
         query = "SELECT CertificateName, CertificateHash FROM UserCertificates WHERE CertificateName='{0}'", param = c.value);

For each column you request in the SQL query, you need a claim type as well.  Also, unlike most SQL queries, to use parameters we need to use a format similar to String.Format instead of using @MyVariable syntaxes.

In a nutshell this is how you deal with claims transformation.  For a more in depth article on how to do this check out TechNet: http://technet.microsoft.com/en-us/library/dd807118(WS.10).aspx.

Modifying and Securing the ADFS 2 Web Application

When you install an instance of Active Directory Federation Services v2, amongst other things it will create a website within IIS to use as it’s Secure Token Service.  This is sort of fundamental to the whole design.  There are some interesting things to note about the situation though.

When Microsoft (or any ISV really) releases a new application or server that has a website attached to it, they usually deliver it in a precompiled form, so all we do is point IIS to the binaries and config files and we go from there.  This serves a number of purposes usually along the lines of performance, Intellectual Property protection, defense in depth protection, etc.  Interestingly though, when the installer creates the application for us in IIS, it drops source code instead of a bunch of assemblies.

There is a valid reason for this.

It gives us the opportunity to do a couple things.  First, we can inspect the code.  Second, we can easily modify the code.  Annoyingly, they don’t give us a Visual Studio project to do so.  Let’s create one then.

First off, lets take a look at what was created by the installer.  By default it drops the files in c:\inetpub\adfs\ls.  We are given a few files and folders:

image

There isn’t much to it.  These files only contain a few lines of code.  Next we create the actual project.

DISCLAIMER:  I will not be held responsible if things break or the server steals your soul.  Please do NOT (I REPEAT) do NOT do this with production servers please!  (Notice I said please twice?)

Since we want to create a Visual Studio project, and since ADFS cannot be installed on a workstation, we have two options:

  1. Install Visual Studio on the server running ADFS
  2. Copy the files to your local machine

Each options have their tradeoffs.  The first requires a bit of a major overhaul of your development environment.  It’s very similar to SharePoint 2007 development.  The second option makes developing a lot easier, but testing is a pain because the thing won’t actually work properly without the Windows Services running.  You would need to deploy the code to a test server with ADFS installed.

Since I have little interest in rebuilding my development box, I went with the second option.

Okay, back to Visual Studio.  The assemblies referenced were all built on Framework 3.5, so for the sake of simplicity lets create a 3.5 Web Application:

image

I haven’t tested 4.0 yet.

Since this is a Web Application and not a Web Site within Visual Studio, we need to generate the *.designer.cs files for all the *.aspx pages.  Right-click your project and select Convert to Web Application:

image

At this point if you tried to compile the application it wouldn’t work.  We are missing a few assembly references.  First, add Microsoft.IdentityModel.  This should be in the GAC or the Reference Assemblies folder in Program Files.  Next, go back to the ADFS server and navigate to C:\Program Files\Active Directory Federation Services 2.0 and copy the following files:

  • Microsoft.IdentityServer.dll
  • Microsoft.IdentityServer.Compression.dll

Add these assemblies as references.  The web application should compile successfully.

Next we need to sign the web application’s assemblies.  If you have internal policies on assembly signing, follow those.  Otherwise double-click the properties section in Solution Explorer and navigate to Signing:

image

Choose a key file or create a new one.  Rebuild the web application.

So far we haven’t touched a line of code.  This is all general deployment stuff.  You can deploy the web application back to the ADFS server and it should work as if nothing had changed.  You have a few options for this.  The Publishing Features in Visual Studio 2010 are awesome.  Right click the project and Publish it:

image

Since I set up a test box for ADFS development, I’m just going to overwrite the files on the server:

image

Pro Tip: If you do something terrible and need to revert back to original code (what part of don’t do this on a production box didn’t make sense? Winking smile) you can access the original files from C:\Program Files\Active Directory Federation Services 2.0\WSFederationPassive.Web.

At this point we haven’t done much, but we now have a stepping point to modify the default behavior of ADFS.  This could range from simple theme changes to better suit corporate policy, or to completely redefine the authentication workflow.

This also gives us the ability to better protect our code in the event that IIS craps out and shows contents of files, not to mention the (albeit minor) performance boost we get because the website doesn’t need to be recompiled.

Have fun!

Presenting at IT Pro Toronto UG on ADFS 2 and Identity Simplification on October 12

Just a heads up that I will be presenting on ADFS in Toronto for the IT Pro User Group.  Here is the write up:

Simplifying User Identity with Active Directory Federation Services (click for link to event)

Start Date/Time:
Tuesday, October 12, 2010 6:30 PM

End Date/Time:
Tuesday, October 12, 2010 9:30 PM

Location:
UofT Health Sciences Bldg, Rm 106, 155 College St.

Description:

There is a growing demand for single sign-on solutions that cross organizational, application and platform boundaries of all sizes.  In this presentation, lets take a look at how we can easily meet these demands using Active Directory Federation Service 2.0 and the Windows Identity Foundation.

Don't worry;  There won't be any code.

Bio:

Steve Syfuhs is a very loud software developer, and works for a large not-for-profit Corporation creating awesome applications.  He has a passion for all things technology, but tries to stick to the fun stuff like the web development, identity management, and telling bad jokes.  His website, www.syfuhs.net, is a collection of random thoughts and ideas that revolve around technology.  And stuff.