SharePoint Calculator Service Part 9 – Claims Auth

One of the game-changing features of SharePoint 2010 is support for claims-based identities. It opens up a whole new set of exciting scenarios by blowing the doors off of the walled garden of the Active Directory. Well, maybe I exaggerate, but only slightly!

In this article, we’ll modify our Calculator service application to support claims-based authentication (AuthN) and authorization (AuthZ).

About Claims-based Authentication

SharePoint has made a big bet on claims-based authentication in the 2010 release. In fact, it is the only type of authentication explicitly supported by the Service Application Framework.

This decision unifies the authentication model used inside a SharePoint server farm and eliminates the complexities around supporting many different types of authentication.

NOTE: SharePoint 2010 still supports many sign-in authentication options such as Windows authentication, for example, when a user signs-in to a SharePoint site from a browser. What we’re talking about here is authentication between the Web Front End tier and the Application Server tier inside a SharePoint server farm.

I feel like I should draw a picture here:

AuthenticationOverview

In this article, we’re specifically talking about the “Claims (only)” arrow connecting the WFE tier to the Application Server tier where our Calculator service application is hosted.

NOTE: It is technically possible to implement your own authentication scheme, but you’ll find that there is no explicit support for this in the Service Application Framework. You’ll end up spending a bunch of time implementing your own authentication and authorization management infrastructure, and your service application will not support the many new scenarios enabled by claims authentication. In short, SharePoint administrators will likely be very unhappy to find this out when they deploy your service.

If you’re interested in more details about some of the scenarios made possible by claims-based authentication, you can read the MSDN documentation or check out the great resources on the SPIdentity blog including three excellent videos linked in this post.

On with the implementation!

First, we need to tell WCF that we want to use claims-based authentication with our service application.

We do that by changing the service binding in our web.config:

web.config

  1. <system.serviceModel>
  2.   <services>
  3.     <service
  4.       name="Sample.Calculator.Service.CalculatorServiceContract">
  5.       <endpoint
  6.         address=""
  7.         contract="Sample.Calculator.Service.ICalculatorServiceContract"
  8.         binding="customBinding"
  9.         bindingConfiguration="CalculatorServiceHttpBinding" />
  10.     </service>
  11.   </services>
  12.   <bindings>
  13.     <customBinding>
  14.       <binding
  15.         name="CalculatorServiceHttpBinding">
  16.         <security
  17.           authenticationMode="IssuedTokenOverTransport"
  18.           allowInsecureTransport="true" />
  19.         <binaryMessageEncoding>
  20.           <readerQuotas
  21.             maxStringContentLength="1048576"
  22.             maxArrayLength="2097152" />
  23.         </binaryMessageEncoding>
  24.         <httpTransport
  25.           maxReceivedMessageSize="2162688"
  26.           authenticationScheme="Anonymous"
  27.           useDefaultWebProxy="false" />
  28.       </binding>
  29.     </customBinding>
  30.   </bindings>
  31. </system.serviceModel>

The interesting change here is that we specify a custom binding (lines 8, 13-29) with an authentication mode of IssuedTokenOverTransport (line 17).

This tells WCF to require a SAML token (containing claims about the authenticating party) in the security header of any messages sent to the service.

The allowInsecureTransport option is required because we’re using HTTP as our transport (line 24), which means that the SAML token will be sent in plain-text over the wire to the service.

This may be appropriate in scenarios where the physical network is considered secure (e.g., a private back-end LAN connecting WFE and App Server) and performance is the primary consideration.

It’s also appropriate for this article because we haven’t yet covered service application endpoints (something we’ll do in the near future).

We’ll also discuss WCF bindings that are supported and work well for service application scenarios in a future article.

But for now, you can just consider the custom binding to be some magic configuration settings that enable our service to work with claims-based authentication.

Next, we need to turn off IIS authentication, because IIS natively doesn’t know anything about SAML tokens. As far as IIS is concerned, connections to our service will be anonymous. Instead, WCF/WIF will take care of authentication.

We do this in web.config as well:

  1. <system.webServer>
  2.   <security>
  3.     <authentication>
  4.       <anonymousAuthentication enabled="true" />
  5.       <windowsAuthentication enabled="false" />
  6.     </authentication>
  7.   </security>
  8. </system.webServer>

Now, as far as IIS is concerned, we have enabled anonymous authentication.

NOTE: I regret that this last step is necessary, as it should have been the default configuration. It’s just one of those things that slipped through the cracks during the release cycle and unfortunately we’re probably stuck with it now, as a change to the default configuration would be a breaking change.

Configuring the Service Host Factory

Next, we need to implement a service host factory. This is necessary because it is the only WCF extensibility point where we can configure the service host for claims support due to the requirement that the service host be configured before it is opened.

NOTE: If you already have a service host factory, you can continue to use it. Just follow along and insert the serviceHost.Configure method call in your CreateServiceHost override as described below.

To do this, we’ll modify our calculator.svc file to reference a new service host factory class:

calculator.svc

  1. <%@ServiceHost
  2.   Language="C#"
  3.   Service="Sample.Calculator.Service.CalculatorServiceContract, Sample.Calculator.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5d38459f57e2f46"
  4.   Factory="Sample.Calculator.Service.CalculatorServiceHostFactory, Sample.Calculator.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d5d38459f57e2f46"
  5. %>

Line 4 is the only change from our original WCF service. It simply tells WCF to call our CalculatorServiceHostFactory when creating our service host.

So now we need to implement the service host factory:

CalculatorServiceHostFactory.cs

  1. internal sealed class CalculatorServiceHostFactory : WebServiceHostFactory
  2. {
  3.     public override ServiceHostBase CreateServiceHost(
  4.         string constructorString,
  5.         Uri[] baseAddresses)
  6.     {
  7.         ServiceHostBase serviceHost = base.CreateServiceHost(constructorString, baseAddresses);
  8.  
  9.         // Configure the service host for claims authentication
  10.         serviceHost.Configure(SPServiceAuthenticationMode.Claims);
  11.  
  12.         return serviceHost;
  13.     }
  14. }

The interesting code here is the call to serviceHost.Configure (line 10). This is a C# extension method implemented in the Microsoft.SharePoint namespace (specifically, in the SPServiceHostOperations class). Don’t be confused by the extension method syntax. The Configure method is not a WCF method on the ServiceHostBase class. It is a SharePoint method.

This method internally does the following:

1. It configures the service host to support authentication via Windows Identity Foundation (WIF).

2. It configures the service host to use an authorization manager that enforces the service application security policy as configured by an administrator.

3. It attaches a WCF behavior (implemented internally by the Service Application Framework) to the service host that handles an optional ServiceContext SOAP message header. A WCF client can use this header to enable correlation of diagnostic information across machine boundaries, to coerce the server thread locale to match the client request locale, and to support multi-tenancy or partitioning of a service application based on a SharePoint site subscription identifier.

Each of these items deserves more explanation, but that’s for another time. For now, rest assured that the Configure method is doing lots of nice things for your service application.

That’s it!

To summarize, we modified our service binding to support issued token authentication, made a single method call to configure our service host, and our service application magically supports claims-based authentication (AuthN) and authorization (AuthZ).

For example, a farm administrator can now use the Permissions button in the Service Applications Management page to grant or restrict access to our service application:

ServiceAppPermissionsButton

By default, any identity that has the “Local Farm” claim will have “Full Control” access to the service application:

ServiceAppPermissions

In effect, this means that any process in the server farm can access the service application. So, services “just work” in a single farm topology by default.

Administrators can customize these permissions to create the advanced topologies I wrote about in a previous post, for example, restricting access to only a specific web application.

Administrators can even use the Publish ribbon button to make the Calculator service application available to clients outside the server farm (“service federation”), and thanks to claims-based authentication, the clients can even be in a different Active Directory domain. In fact, the clients don’t even have to be a member of a Windows domain or have an Active Directory available at all!

As with the Administrators ribbon button that we look at in my last post, service implementers can customize the permissions to provide more granularity than just “Full Control” and enforce these permissions on a per-method basis rather than the basic “all-or-nothing” access enforced by the Connection Permissions settings.

Identity Delegation

Another feature we now have available to our service application is the end-user identity. We can inspect the end-user’s identity (as signed-in on the Web Front End) all the way back in the App Server tier where our service application is executing.

This may seem like an obvious thing, but it wasn’t possible with Windows authentication without a PhD in Kerberos and domain administrator-level access to the Active Directory, because a feature called “delegation” of the user token is required to flow a Windows identity across multiple servers.

Not so with SharePoint claims-based identities. Delegation works out of the box, no PhD required.

We’re not taking advantage of this feature yet, but I’ve got a cool feature planned for the Calculator service that will make good use of it in a future article.

Enjoy!