In my previous post, I demonstrated how to enable a SharePoint 2010 web application for claims authentication. As a result, it could be seen that all relevant windows account information (account SID, logon name, group membership) is automatically consumed from Active Directory by the SharePoint Security Token Service (STS) and transformed into claims, which as the basis for the SPUser object. Except for a handy web part, no extra configuration required. It’s all “out of the box”.I then went on to show how to extend this model by federating SharePoint with ADFS 2 .0. That demonstration, based on this article from the TechNet library, put SharePoint 2010’s built-in Security Token Service in the role of a Relying Party (RP-STS) and the WS-Federation passive endpoint of ADFS 2.0 server in the role of an Identity Provider (IP-STS). After completing this exercise, you may have asked yourself what the point of doing all this might be. It’s the intention of this article to hopefully answer that question and show why using ADFS 2.0 in this way can be a very powerful option for all SharePoint 2010-based extranets and public-facing Internet sites.
ADFS 2.0, formerly known as “Geneva Server”, can act as a centralized hub for managing user identity and trust relationships between applications, web services and, by extension, organizations. User identity is typically expressed as claims, which are documented in SAML, a type of specially formatted, digitally signed XML. As long as applications can “speak” one of the web standards defined by (WS-Trust or WS-Federation), they can consume from or provide identity to ADFS 2.0. This is implemented in ADFS 2.0 via two kinds of trust relationships: Claims Provider Trusts and Relying Party Trusts. My previous post involved configuring a Relying Party Trust for a claims-enabled web application in SharePoint 2010 with claims being provided by ADFS 2.0 after users authenticate via Windows Integrated authentication. A Claims Provider Trust allows for that authentication process to be extended to other internal or external identity providers.
Before I go much further, I want to state much of this is based on Matias Woloski’s excellent article posted back in July of last year. It discusses the concept of a “Transition STS” that converts OpenID claims into SAML claims and raises the possibility of plugging it into ADFS 2.0 as a Claims (identity) Provider. It’s a powerful example because it clearly shows how well this technology integrates. I essentially implemented what he proposed using the current ADFS 2.0 Release Candidate and the current, public beta of SharePoint 2010. From an architecture perspective, the design pattern is as follows:
This diagram is an elaboration based on Matias Woloski’s and includes ADFS 2.0 as the central “hub” for various WS-Federation relationships. A couple of observations come to mind with this:
- You can see how the entire authentication and identity discovery process is highly modularized (or “pluggable”) with centralized control being provided by ADFS 2.0. You can pretty much add any application on your network into this model by creating a WS-Federation compliant STS for it. This is relatively easily accomplished if you’re familiar with the concepts introduced in the Identity Developer Training Kit. And Microsoft provides tools and templates for Visual Studio as part of the Windows Identity Foundation SDK that do a lot of the work for you. If you haven’t already, I highly recommend you check it out.
- Since we’re dealing with web services and standard protocols here, it doesn’t really matter if an IP-STS is internal or hosted in “the cloud”. As an example, full, “out of the box” support for using Windows Live credentials will be included in the RTM version of ADFS 2.0. Integration with the Microsoft Federation Gateway and the Windows Azure Access Control Service will likely be common scenarios as well. Essentially, where authentication happens and how user information flows back to your applications is entirely up to you.
- Identity in SharePoint 2010 is based on the Windows Identity Foundation (WIF). I’m sure you noticed “Geneva” framework” as a pre-requisite for installing the beta SharePoint Foundation. WIF fully supports all the protocols we’ve mentioned so far. In fact, in a claims-mode Web Application the SPUser object is hydrated from claims embedded in IClaimsPrincipal. There is no difference with how claims are received and processed in SharePoint 2010 as with any “Geneva-enabled” ASP.NET page. This is no surprise given SharePoint’s relationship with ASP.NET, but it’s worth at least pointing out. There is no SharePoint object model “trickeration” going on here.
So your SharePoint 2010 environment can essentially outsource the authentication process to one or more (internal or external) identity providers (Google, Windows Live, a trusted Active Directory instance, OAuth, etc…) and consume whatever identity information is provided / required. This has many important ramifications for the end-user experience, how personal information is (or is not) disclosed, and how SharePoint 2010 can be used as a social / content platform. For example, if you’re hosting content that requires a user to subscribe to your service using a named account, you can create a trust relationship with a series of well known external identity providers instead and just direct the user to authenticate to them using their existing user IDs and passwords. You are off the hook for managing accounts (creation, password resets / expiration) and you have arguably less exposure to the disclosure of personally-identifiable information since you aren’t storing anything. Users also win because they get out of having to create and remember yet another user ID and password and I would argue this can lead to an increase in adoption and / or re-use of the content.
Let’s take a look at a concrete example. We’re going to set things up so we can “log in” to a claims-mode SharePoint 2010 web application using an OpenID account. NOTE: It is assumed you have successfully configured a claims-mode SharePoint web app to federate with ADFS 2.0. This is a prerequisite and if you have not done this already, please see my previous blog on the subject. I’ll break this process down into two main steps: Configure the WS-Fed Protocol Transition STS and Configure a Claims Provider Trust for ADFS 2.0.
Configure the WS-Fed Protocol Transition STS
You’ll need to have the following prerequisites done before starting the configuration:
- Download the code example provided by Martin Woloski. Unzip the contents to a convenient location. You should have a single folder called WSFedWebsiteAndOpenIDSTS with two folders inside of it. We will need source code provided within these two sub-folders.
- Enroll for an OpenID account through myopenid.com. You will need this in order to sign into ADFS 2.0 and, by extension, a claims-mode SharePoint 2010 web application.
- Download and install the Windows Identity Foundation SDK. This SDK includes tools (FedUtil) and templates for Visual Studio. As far as I can tell, these tools and templates work fine in Visual Studio 2010.
Start by creating a new ASP.NET web site in Visual Studio (File > New Web Site). In my example, I’m setting the web location to http://pbdev.com/OpenIdTestSite. You can do the same to “localhost” if you wish.
- Right-click the site properties and select “Add STS Reference…”. This starts the Federation Utility Wizard (FedUtil). Accept the defaults and click “Next” at the first screen. You may see a warning stating the application is not hosted using HTTS. This is OK to ignore for now.
- On the next screen, click the radio button for “Create a new STS project in the current location” and click Next. Finish the wizard. You will now see a second site appear in the Solution. This is the new STS and it is represented with an “_STS” suffix.
- Copy the contents of default.aspx.cs from the code example WSFedWebsite directory to the corresponding default.aspx.cs file in your test web site.
- Copy the contents of the Bin folder under the code example OpenIdWSFedSTS folder to the corresponding location of your new _STS site. This should create a new Bin directory in Visual Studio.
- Copy the contents of Login.aspx from the code example OpenIdWSFedSTS directory into the corresponding Login.aspx folder in your _STS site.
- Copy the contents of Login.aspx.cs from the code example OpenIdWSFedSTS directory into the corresponding Login.aspx.cs folder in your _STS site.
- Validate there are no compile errors for Login.aspx.cs in your _STS site.
This completes the setup process. Go ahead and launch http://<<yoursite.com>>/OpenIdTestSite. You should be immediately redirected to the STS login page, which hosts the OpenID control.
You will be redirected to authenticate to your myOpenID account.
Follow the on-screen instructions and you will be redirected to your test site with your claims displayed.
If you’ve gotten this far, you now have the fundamentals working with a basic ASP.NET example. Now it’s time to plug this into ADFS 2.0 so this can be used for SharePoint 2010 access!
NOTE: All claims tokens are digitally signed by the issuing STS using an X.509 certificate. Before we move on with configuring ADFS, we should identify this certificate and export it as a .CER file. You should be able to find the name of this certificate in the key “SigningCertificateName” in the web.config of your custom STS. Once you have the name, export it as a DER encoded binary (.CER) using the “Certificates” MMC snap in. Make sure you specify “computer account” when starting the snap-in.
Configure a Claims Provider Trust for ADFS 2.0
The IT Leader's Guide to Multicloud Readiness
This guide provides practical key insights and important factors to consider to make informed decisions in your multicloud journey.
Download the Guide
Next we need to set up our custom STS as a claims provider. This is done by launching the AD FS 2.0 Management Console, expanding the “Trust Relationships” node, right clicking “Claims Provider Trusts”, and selecting “Add Claims Provider Trust…”. This launches a handy wizard.
- Click “Start” at the welcome screen.
- At Select Data Source, select the radio button for “Enter claims provider trust data manually”
- At Specify Display Name, enter a value and click Next.
- At Choose Profile, select AD FS 2.0 profile and click Next
- At Configure URL, select “Enable support for the WS-Federation Passive protocol”. For the URL, enter the URL of your STS: http://<<yoursite.com>>/OpenIdTestSite_STS. Note that SSL is a requirement here. If the site under which your STS is located is not enabled for SSL, go ahead and enable it in IIS. When done, click Next.
- At Configure Identifier, leave the default value, which is the URL provided in the previous step. Click Next
- At Configure Certificates, browse to the location of the .CER file you created at the end of the previous section. Click Next.
The next step is to create claim rules for our new claims provider. This is necessary to pass on information from ADFS 2.0 to the SharePoint 2010 STS. This is done by right-clicking the new provider from the AD FS 2.0 Management console and selecting “Edit Claim Rules”. Follow these steps:
- Click the “Add Rule” button
- At the Choose Rule Type section, select “Pass Through or Filter an Incoming Claim” and click Next
- At the Configure Claim Rule section, enter “Passthrough: Role” for the Claim rule name. For Incoming claim type, enter Role. Ensure the radio button for “Pass through all claim values” is selected.
- Repeat this process for Name and Authentication claims
- Click the “Add Rule” button
- At the Choose Rule Type section, select “Transform an Incoming Claim” and click Next
- At the Configure Claim Rule section, enter “Transform: Build Email Address” for the Claim rule name. For Incoming claim type, enter Name. For Outgoing claim type, enter E-Mail Address. Ensure the radio button for “Pass through all claim values” is selected.
Your claims rule configuration should now look like the following:
Add ReplyToAddress Logic to the Custom STS
Before we test this out, we need to make one more change to our custom STS. ADFS 2.0 does not provide a ReplyToAddress to our custom STS. There are some good reasons for this, but that’s probably a topic for a separate posting. Anyhow, the STS developer is responsible for mapping the identifier of the calling STS to it’s actual WS-Federation passive endpoint URL. You can find out what your identifier is by highlighting the “Service” node in the AD FS 2.0 Management console and clicking “Edit Federation Service Properties”. You can see from the following screenshot that the identifier in my case is “http://pbdev.com/adfs/services/trust”.
So I need to provide a mapping in my custom STS between this identifier and actual URL, which is “https://pbdev.com/adfs/ls/”. This is done in the GetScope method within CustomSecurtyTokenService.cs. See lines 30 – 37.
- protected override Scope GetScope( IClaimsPrincipal principal, RequestSecurityToken request )
- ValidateAppliesTo( request.AppliesTo );
- // Note: The signing certificate used by default has a Distinguished name of “CN=STSTestCert”,
- // and is located in the Personal certificate store of the Local Computer. Before going into production,
- // ensure that you change this certificate to a valid CA-issued certificate as appropriate.
- Scope scope = new Scope( request.AppliesTo.Uri.OriginalString, SecurityTokenServiceConfiguration.SigningCredentials );
- string encryptingCertificateName = WebConfigurationManager.AppSettings[ “EncryptingCertificateName” ];
- if ( !string.IsNullOrEmpty( encryptingCertificateName ) )
- // Important note on setting the encrypting credentials.
- // In a production deployment, you would need to select a certificate that is specific to the RP that is requesting the token.
- // You can examine the ‘request’ to obtain information to determine the certificate to use.
- scope.EncryptingCredentials = new X509EncryptingCredentials( CertificateUtil.GetCertificate( StoreName.My, StoreLocation.LocalMachine, encryptingCertificateName ) );
- // If there is no encryption certificate specified, the STS will not perform encryption.
- // This will succeed for tokens that are created without keys (BearerTokens) or asymmetric keys.
- scope.TokenEncryptionRequired = false;
- // Set the ReplyTo address for the WS-Federation passive protocol (wreply). This is the address to which responses will be directed.
- // In this template, we have chosen to set this to the AppliesToAddress.
- if (scope.AppliesToAddress == “http://pbdev.com/adfs/services/trust”)
- scope.ReplyToAddress = “https://pbdev.com/adfs/ls/”;
- scope.ReplyToAddress = scope.AppliesToAddress;
- return scope;
Once this is done, you should be able to browse to your claims-enabled SharePoint 2010 Web Application and get redirected to the ADFS 2.0 sign-in page. Since we now have two claims providers (Active Directory and OpenIdTest), we need to choose an authentication method using the drop-down listbox.
The OpenID sign-in process is exactly the same as shown earlier. After authenticating into MyOpenID, you should be re-directed to SharePoint with Viewer permissions.
The following table provides a closer look at the resulting claims in SharePoint 2010.
Note that we could (1) add more output claims to our custom STS (where possible) by modifying the GetOutputClaimsIdentity method within the CustomSecurityTokenService class, (2) create additional claim rules for our OpenID claims provider in ADFS 2.0 to feed those claims to SharePoint 2010, and (3) add additional inbound claim mappings on SharePoint (we just have one here for ‘emailaddress’) to accept those claims and further enhance the user property information. And, indeed, how claims are used and processed within SharePoint 2010 is a whole new topic in itself!
Hopefully, you can see this approach can be adapted to a wide variety of identity providers like OAuth (Twitter, LinkedIn, Google, NetFlix, etc…) and Shibboleth. You only need “plug in” a single Transition STS for each provider to an instance of ADFS 2.0. Your internal (or Azure-hosed) applications and services only need to use Windows Identity Foundation (WS-Federation) to consume user identity from these providers (through ADFS 2.0) without any coding. Furthermore, we have already shown that the entire identity model for SharePoint 2010 was written based on this framework, so it works very well with this technology at a significantly lower level of effort than before. Additionally, you should now have a sense of how ADFS 2.0 can be an extremely valuable tool to centrally manage trust relationships and handle the flow of claims across an entire spectrum of identity consumers and providers. I hope you’ll agree this is a major step forward for the SharePoint platform.