Category Archives: Identity

Claims Proxy – A C# Library for Calling Claims Protected Web Services

The ClaimsProxy library enables you to get a WIF cookie collection for a SharePoint site which is protected by Claims Based Authentication. It assumes that ADFS is configured as the Trusted Identity Token Issuer and that the down-stream identity provider is based on the StarterSTS / IdentityServer project.

In some recent work I needed to call some SharePoint 2010 web services from a client outside of the SharePoint farm.  Using traditional network credentials and Windows Authentication this was a straightforward matter, for example:


ICredentials credentials = new NetworkCredential('username', 'password', 'domain');
SharepointUserGroupsWCF.UserGroupSoapClient client = new SharepointUserGroupsWCF.UserGroupSoapClient();
client.ClientCredentials.Windows.ClientCredential = (NetworkCredential)credentials;
client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
client.Endpoint.Address = new EndpointAddress(webPath + "/_vti_bin/usergroup.asmx");

XElement groupXml = client.GetGroupCollectionFromSite();

However, when the target service is protected by Claims Based Authentication, it’s not so straightforward to call such services.  In my scenario I had a SharePoint 2010 site protected in a web application configured with Claims Based Authentication.  I had configured SharePoint to direct authentication to ADFS (Microsoft Active Directory Federation Server), and then I had a custom claims provider configured based on Dominick Baier’s Identity Server  open source STS product (formerly StarterSTS), however my approach could easily be adapted to work with any number of final claims providers.

Even if you just want the code, read this bit first.

I’ve implemented the code as a .NET 4.0 assembly, although it should be relatively easy to get it to compile under .NET 3.5.  The overall approach works as follows:

  • Use username + password to request a symmetric token from our custom STS (you could get a Windows token here or whatever you are using) – set the realm to that configured for ADFS
  • Use that token to request a bearer token from ADFS – set the realm to the SharePoint site realm as configured in ADFS
  • Use the token from ADFS to authenticate with SharePoint
  • From the resulting authentication response, extract the WIF (Windows Identity Foundation) cookie for authentication (commonly named FedAuth)
  • Return this cookie to the client

I have included a test application in the solution which demonstrates using the returned cookie to make a call to a web service in the SharePoint site.  I’ve left the responsibility of caching the cookie to the client (but included this in the test app).

IMPORTANT NOTE: There is one modification required to the library which I haven’t done yet.  If you read the finer details of WIF you will know that if the SAML token data is too large for a single cookie, then WIF spreads the data over multiple cookies named FedAuth1, FedAuth2 … FedAuthN.  The library assumes that there is only one FedAuth cookie at present – which will be sufficient for most applications – but its worth keeping an eye on if you’re running into troubles.  I will get around to sorting this at some point, but feel free to make a pull request on my Github repository if you get there first.

Download the ClaimsProxy library and sample application from Github

ClaimsProxy is straightforward to use:


// configure our SPServiceRequestor.
var requestor = new SPServiceRequestor
{
    DobstsEndpoint = "https://startersts.yourdomain.com/startersts/users/issue.svc/mixed/username",
    DobstsUsername = "joe.bloggs@yourdomain.com",
    DobstsPassword = "password",
    DobstsAdfsRealm = "https://adfs.yourdomain.com/adfs/ls/",
    AdfsEndpoint = "https://adfs.yourdomain.com/adfs/ls/",
    SharepointRealm = "urn:sharepoint:sp.yourdomain.com",
    SharepointSiteUrl = "https://sp.yourdomain.com/",
    IgnoreSslValidation = true,
    DebugMode = true,
    DebugEventCallback = (data) =>
    {
     // your debug function here
    }
};

string spCookieRaw = requestor.GetCookie();

N.B.: DobSts is our own implementation of the StarterSTS project.

Check out the sample application for a full example of how to use the library.

I’d welcome any comments / feedback on this – hopefully it will be of some use to others out there, it certainly has been to me.

Setting up Google Apps Single Sign On (SSO) with ADFS 2.0 and a custom STS such as IdentityServer

I recently had to undertake some work to enable users to seamlessly authenticate to Google Apps using an identity stored in a custom Secure Token Service such as the excellent IdentityServer open source STS by Dominick Baier.  The work involved is mostly configuration in Google Apps and ADFS but there are quite a number of steps and as it was non-trivial I thought I’d document it here for reference.  Note that Google Apps uses SAML 2.0 tokens and because ADFS is brokering the authentication, you shouldn’t have any problems with compatibility as ADFS 2.0 can issue SAML 2.0 tokens.

Here’s a quick architecture diagram:

google-sso-adfs

Key:

Green arrows = user request flow

Blue arrows = service response flow

Overview

For those of you impatient, here’s a quick overview of the steps required:

  1. Enable SSO in Google Apps
  2. Enter correct ADFS urls into Google Apps
  3. Upload ADFS Token Signing Certificate so Google Apps can verify the SAML tokens
  4. Add Google Apps as a Relying Party in ADFS
  5. Test

I will now walk through each stage in detail, for those who like the details.

Enable SSO in Google Apps

The first stage is to enable Single Sign-on in Google Apps.  Log in to your administration console at /">http://www.google.com/a/<your-domain>/.  Click on Advanced Tools and in the Authentication section click on Set up single sign-on (SSO):

step01

This will take you through to a configuration screen.  Make sure the checkbox next to Enable Single Sign-on is ticked, and then enter the following values:

Sign-in page URL: https://adfs.yourdomain.com/adfs/ls/

Sign-out page URL: https://adfs.yourdomain.com/adfs/ls/

Change password URL: https://sts.yourdomain.com/startersts/users/password.aspx

Verification certificate: Upload the ADFS Token Signing cert (.cer file) which you can obtain from the AD FS 2.0 Management Console (under Service > Certificates).  Remember to click Upload.

Check the box next to “Use a domain specific issuer”.

Enter some network addresses into the Network masks box if you wish.

step02

At this point Single sign-on is configured and enabled.  Note that this will take immediate effect on your access to Google Apps services so beware!  However it does not affect your login to the admin console – that is always accessed via a manual login, so you can get in and turn it off again.

Configure ADFS

Open up the AD FS 2.0 Management Console and navigate to the Relying Parties section.  Click Add Relying Party Trust and follow these steps:

Choose Enter data about the relying party manually

step03

Provide a name for the trust (not important, only so you can easily identify it)

step04

Choose AD FS 2.0 profile

step05

Tick Enable support for the SAML 2.0 WebSSO protocol and enter /acs">https://www.google.com/a/<your-domain>/acs into the Relying party SAML 2.0 SSO service URL

step06

Enter google.com/a/<your-domain> as the relying party identifier

step07

Complete the wizard.

Then click on the newly added item and click Properties.  Click on the Signature tab and click add:

step08

Here we add the Token Signing Certificate – it must be the same one that we uploaded in the Google admin console, and this should be the ADFS Token Signing Certificate.

Once you’ve done that click OK to close the Properties dialog.

Now click Edit Claim Rules and click Add Rule:

step09

Select Transform an Incoming Claim from the Claim rule template drop-down:

step10

Give the rule a name, select E-Mail Address as the Incoming Claim Type, set the Outgoing claim type to Name ID and the Outgoing name ID format to Email:

step11

Finish the wizard.

Test

I’ve assumed here that you’ve already got your custom STS configured as a Claims Provider in ADFS.  To test the end-to-end service, visit http://mail.google.com/a/<your-domain&gt;.  You should get redirected to ADFS.  Choose your STS and then enter your credentials.  You should then be redirected back to Google Apps and arrive at your mailbox, logged in.

If you hit problems, check these items:

– You’ve got the correct certificate uploaded to Google Apps and configured in ADFS

– The time on the ADFS server and custom STS servers is correct

– Google Apps SSO configuration is correct

– If all else fails, try Googling!

How to run StarterSTS on IIS 6 / Windows 2003

I’ve been using the awesome StarterSTS project created by Dominick Baier.  In the words of Dominick:

StarterSTS is a compact, easy to use security token service that is completely based on the ASP.NET provider infrastructure. It is built using the Windows Identity Foundation and supports WS-Federation., WS-Trust, REST, OpenId and Information Cards.

The StarterSTS System Requirements specify IIS 7.x which implies a Windows 2008 variant operating system.  I recently had a requirement to get it running on a Windows 2003 server (with IIS 6), and it isn’t all that straightforward so I thought I’d post the steps (and as much reasoning as possible here).

Prerequisites

You’ll need the following things to hand to get going:

Installation

Follow the StarterSTS instructions to extract the web package and create the site in IIS.  Make sure you install the SSL certificate on the IIS web site, and follow the subsequent instructions to set up the relevant StarterSTS configuration files.

If you haven’t installed the WIF package you’ll get an error similar to this:

Could not load file or assembly Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 or one of its dependencies. The system cannot find the file specified.

Run the WIF install package and that error will go away.

You should then be able to bring up the StarterSTS homepage:

sshot-7

Go ahead and create yourself a user account by visiting /signup.aspx (remember to create the database as in the StarterSTS instructions):

sshot-8

Token Issuance

This is where the configuration gets a bit more involved.

Note: The auto-generation of federation meta-data doesn’t work on IIS 6 (normally you would hit /FederationMetadata/2007-06/FederationMetadata.xml).

Try visiting the following URL:

https://sts.gws.lab.local/startersts/users/issue.aspx?wa=wsignin1.0&wtrealm=http://adfs.leastprivilege.vm/adfs/services/trust

(Remember to replace the first part with the address of your server.  The value of wtrealm depends on what you’ve put in the configuration/relyingParties.config file in StarterSTS.  In this example I’m just using the sample entry that comes with the source download.)

The first error you’ll see is:

The handle is invalid. System.Security.Cryptography.CryptographicException: The handle is invalid.

This error comes about because the identity of the IIS Process executing the StarterSTS code cannot access the private key of your signing certificate (as specified in configuration/certificates.config).  In Windows 2008, this is easily fixed using the Certificates MMC Snap-In, but not so in Windows 2003 (the option isn’t available).  This is where the WinHTTPCertCfg tool comes in handy.  It allows us to check and set the user identities with access to certificates installed on the machine [read X509 Certificates on Windows Server 2003 for more info].

If you followed the default install settings, then the tool will have installed to c:Program FilesWindows Resource Kitstools.  Open a Command Prompt, switch to this directory and run the following command to see which user identities have access to the certificate:

winhttpcertcfg.exe -l -c LOCAL_MACHINEMy -s "sts.gws.lab.local"

sshot-3

Note: Replace the “sts.gws.lab.local” with the Common Name on your certificate.

Now you need to check which user is running IIS.  This is done by looking at the properties on the Application Pool assigned to the StarterSTS virtual directory:

UntitledUntitled2

My server is running with the out-of-the-box account Network Service.  Now that we know this, we can go back to the Command Prompt and grant this account permissions over the private key:

winhttpcertcfg.exe -g -c LOCAL_MACHINEMy -s "sts.gws.lab.local" -a "NetworkService"

sshot-4

Restart IIS and go back to the the issue.aspx URL and you’ll likely get this error now:

Object identified (OID) is unknown. System.Security.Cryptography.CryptographicException: Object identifier (OID) is unknown.

sshot-5

This comes about due to the need to configure RSA-SHA256 on Windows 2003.  For more details on this see this MSDN Forum Post – CryptographicException – Object identifier (OID) is unknown.  Follow the steps in the forum answer:

using Security.Cryptography;

class Program
{
    static void Main(string[] args)
    {
        Oid2.RegisterSha2OidInformationForRsa();
    }
}
  • Build and run the console application (alongside the DLL) on the server

Alternatively, save yourself the hassle and download the ZIP that I made earlier.

After that, everything should fly, and StarterSTS should issue a token and redirect you back to the relying party specified in the wtrealm parameter.  I grabbed a couple of screenshots using Fiddler to show it working:

sshot-6

And that’s it!  I hope this has been helpful, it was very rewarding when I got this working and I have repeated it several times on different boxes.