========================================================
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, whereauthentication 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 exampleprovided 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. Note that the only claims we get back from this provider is the ‘name’ claim. This makes sense given that we’re only using OpenID or user authentication. OpenID has no knowledge of the roles this user should have within SharePoint. But having this claim is good enough for us to (a) confirm the user is authenticated and (b) establish a unique identifier for the user.
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
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: https://[your site host header]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.
- At the Finish window, leave the checkbox selected and click Close.
You will immediately see a new window where we need to specify the “Acceptance Transform Rules”. These rules handle the inbound claims from our custom STS. This is part 1 of a two part process to pass on information from ADFS 2.0 to the SharePoint 2010 STS. Follow these steps:
- 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, type “Convert name claim to UPN claim” for the rule name. For Incoming claim type, enter ‘Name’. For the outgoing claim type, enter ‘UPN’. Ensure the radio button for “Pass through all claim values” is selected.
Your claims rule configuration should now look like the following:
The second part of involves adding an “Issuance Transform Rule” so that our inbound claims can be passed back to our SharePoint web application. Select the Relying Party Trusts folder under Trust Relationships and highlight the relevant relying party you configured earlier. In the Actions Pane, click Edit Claim Rules… and complete the following steps:
- Click the “Add Rule” button
- In the next window, select the claim rule template: “Pass through an Incoming Claim”
- At the next window, enter the claim rule name OpenID: UPN. Set the incoming claim type to ‘UPN’. Make sure the radio button for “Pass through all claim values” is selected.
Add Reply Address 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://SP2010.pbdev.local/adfs/services/trust.
So I need to provide a mapping in my custom STS between this identifier and actual URL. This is done at the end of the GetScope method within CustomSecurtyTokenService.cs. See lines 1 – 4 below.
1: if (scope.AppliesToAddress.ToLower() == "http://sp2010.pbdev.local/adfs/services/trust")
2: {
3:
scope.ReplyToAddress = “https://sp2010.pbdev.local/adfs/ls/”;
4: }
5: else if (scope.AppliesToAddress == "urn:contoso:openid")
6: {
7: scope.ReplyToAddress = "http://contoso/_trust/";
8: }
9: else
10: {
11: scope.ReplyToAddress = scope.AppliesToAddress;
12: }
13:
14: 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.
NOTE: If your web application uses both ADFS and Windows Integrated authentication, users will actually have two identity selector menus: one for SharePoint and one for ADFS. The SharePoint menu can be removed by un-checking Windows Integrated authentication in Central Admin. Be sure you have a valid claims principal assigned as site collection administrator before you do this, though.
Once the user selects the OpenID STS, the sign-in process is exactly the same as shown with the test site earlier. Assuming you configured ADFS according to the steps outlined in my previous post, you will be redirected to your claims-enabled web application with read permissions.
Note that we could (1) add more output claims to our custom STS (where possible) by modifying the GetOutputClaimsIdentity method within the CustomSecurityTokenService class, or (2) configure ADFS to look up additional claims stored in a SQL or LDAP repository for this user to populate, for example, application roles. Either way, making these changes would require us to (1) define more Issuance Transform Rules on the Relying Party Trust in ADFS so that the information is passed back to SharePoint. and (2) add additional inbound claim mappings to our SP-TrustedIdentityTokenIssuer settings on SharePoint so the claims are processed and added to the SPUser object.
Hopefully, you can see this approach can be adapted to a wide variety of identity providers that don’t “speak” SAML like OAuth (Twitter, LinkedIn, Facebook, NetFlix, etc…), Shibboleth, and almost anything else you can think of. You only need plug in a “transition” STS for each type of provider to an instance of ADFS 2.0. All the complexity is facaded away from SharePoint. 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. Finally, 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.