Download the code for this article here.

In my last article, "Access Control in the Cloud: Windows Azure AppFabric's ACS," I provided an overview of the Access Control Service (ACS)—a feature of Windows Azure AppFabric alongside the Service Bus. You learned how to set up a Service Namespace for AppFabric so that clients can request tokens from the ACS to authenticate to protected web resources, and you learned about the underlying protocols supporting this flow of communication. In this article, I will dive deeper into the specifics of how the ACS can be used to protect REST-based services built with WCF. Specifically, I'll show you the code to request ACS tokens and authenticate to the service and the code required at the service to authenticate the token and authorize access based on the claims carried within. In the process, I'll show you how to use a set of components that encapsulate this functionality for clients and services and make it possible to integrate with classic Windows Communication Foundation (WCF) and Windows Identity Foundation (WIF) security models at the service.

Scenario Overview
First let me explain the features of the scenario for this article—which will also serve as review for those who didn't catch my introduction to the ACS. From a high level, this scenario involves a Windows client (TodoListClient), a REST-based WCF service (TodoListService) called by the client, and of course the ACS to secure the service. The client will be distributed to administrators and to read-only users—and for this scenario, a unique ACS issuer will be provided for each of these users, each with a unique issuer key distributed with the client application. Figure 1 provides additional details relevant to the flow of communication between each of these participants.

Figure 2 shows the ACS Management Browser view of the configuration for this scenario. The left side shows the list of issuers, scopes and rules, and token policies. In the screenshot, the GrantReadOnly rule is displayed. Specifically, here are the details of the ACS resource model for the scenarios illustrated in Figure 1 and Figure 2:

  • Token Policy: The TodoListService will reject requests unless they present a token signed by the TodoListTokenPolicy. The token policy key used to sign issued tokens is a shared secret also used by the TodoListService to authenticate the token presented with each request.
  • Scope: A scope is created for requests sent to the TodoListService Uri. The scope has a number of rules that determine which claims to issue for the request. If the client presents a request to the TodoListAdmin issuer, the Issuer claim will be "TodoListAdmin" and this will result in issuing Create, Read, Update, and Delete permission claims. The value of the LicenseKey permission is passed through. Figure 3 lists the rules configured for this scope in greater detail.
  • TodoListAdmin Issuer: Requests sent to the TodoListAdmin issuer must include a token signed with the TodoListAdmin issuer key. The issuer key is a shared secret between the client application and the issuer. The client application also includes the LicenseKey claim in this token, so that it will be passed through to the service for further evaluation.
  • TodoListReadOnly Issuer: Requests sent to the TodoListReadOnly issuer must include a token signed with the TodoListReadOnly issuer key. The client application also includes the LicenseKey claim in this token for pass-through.

The client application creates a Simple Web Token (SWT) containing the LicenseKey claim and sends it to the appropriate issuer—the token signed with the issuer key. After evaluating the appropriate rules for the scope of the request, the ACS issues a SWT token carrying the outgoing claims, signing it with the token policy key. The client then presents this token with requests to the service. Once the incoming token is validated, the service evaluates the issued claims to enforce authorization. I'll dive deeper into the details of this process shortly.

ACS Utility Classes
Code samples included in the AppFabric SDK provide the raw materials to code up requesting tokens from the ACS, passing those tokens with each request to the service, and processing the token at the service. In this article I will show you how to achieve the same using some custom components I created to encapsulate this functionality. Figure 4 illustrates the relationship between these components, and the core set of properties and methods exposed by each. To summarize:

  • AccessControlConfiguration: Clients and services initialize this type with their respective ACS settings including the service namespace, request scope, and respective client and service key materials.
  • SWTToken: This component is at the heart of it all, representing a SWT token instance. Every token has an issuer, intended audience, expiry, and a set of claims—all signed with the specified issuer key. This type can be initialized in three ways. Clients use the SWTTokenHandler to produce a new token, it can be hydrated from the response from a token request to the ACS, and it can be hydrated from the Authorization header passed to services. The SWTToken type also provides functionality to validate token signatures.
  • SWTTokenHandler: This component manages the creation of SWTToken instances using the application's AccessControlConfiguration settings and settings specific to the token to be created such as the intended audience, issuer name and key, and token lifetime. Claims are also supplied to create a token. The SWTTokenHandler also handles validation of tokens.
  • SWTTokenDescriptor: This type supplies information to the SWTTokenHandler for constructing a new token.

Now that you have an idea of what each component does, I'll walk you through the code required to create tokens, send token requests to the ACS, send tokens to the service for authentication and authorization, and authorize access at the service.

Requesting Tokens from the ACS
As mentioned in my previous article, when you request a token from the ACS, you can do so in two ways: in plain text or as a signed assertion. When you send a plain text token request, you supply the token issuer name and secret key along with the scope each as form-encoded parameters:

wrap_name=TodoListAdmin<br>wrap_password= 8ISHl0yzcsiy9EAdznMMvociTuXlgPTXI2KZ/9x8IyY=<br>wrap_scope=http://localhost:8000/TodoListService


Signed requests require you to pass a signed assertion (either SWT or SAML) along with the scope. Here are the parameters passed for an SWT example:

wrap_assertion_format=SWT<br>wrap_assertion=LicenseKey=abc123&Issuer=TodoListAdmin&Audience=https://bustacloudsamples.accesscontrol.windows.net/WRAPv0.9&ExpiresOn=1267782576&HMACSHA256=YfSVv7gnL6Yj2LFaOzONx9pvYL0WNEEACxhvLQ%2fwjAk%3d<br>wrap_scope=http://localhost:8000/TodoListService


Both mechanisms are secured with HTTPS; however, it is generally preferred to send a signed assertion, so I will focus on that implementation here. The first step is to create and sign the SWT to be used for authentication to the ACS. This SWT must include the following information, as shown in the earlier wrap_assertion parameter:

  • any claims you should pass to the ACS for evaluation and transformation
  • the name of the token issuer that the client will authenticate to
  • the intended audience of the SWT, which in this case is the ACS base issuer endpoint
  • a value indicating the expiry time of the token
  • an HMAC signature from the unsigned token including the above values

Figure 5 illustrates the code required to generate a SWT token using the utility classes from Figure 4 and subsequently request a token from the ACS. To create a SWT token to authenticate to the ACS, first the AccessControlConfiguration type is initialized with the required ACS account settings. For completeness I am showing how to set all properties, but the first four settings are actually the defaults when the type is constructed, so it isn't necessary to set those values explicitly. The code then creates a new SWTTokenHandler and calls CreateToken() to produce an SWTToken instance. CreateToken() requires you to pass the claims to be added to the token, but all other settings to produce a token are derived from the AccessControlConfiguration or from the default instance of the SWTTokenDescriptor, as shown here in the implementation:

public SWTToken CreateToken(NameValueCollection claims)<br>\\{<br>  SWTTokenDescriptor descriptor = new SWTTokenDescriptor();<br>  descriptor.Issuer = AccessControlConfiguration.Current.ClientIssuerName;<br>  descriptor.IssuerKey = AccessControlConfiguration.Current.ClientIssuerKey;<br>  descriptor.Audience= AccessControlConfiguration.Current.IssuerAddress;<br>  descriptor.TokenLifetime = AccessControlConfiguration.Current.TokenLifetime;<br><br>  SWTToken token = new SWTToken(descriptor, claims);<br>  return token;<br>\\}


In Figure 5, the client sends a LicenseKey claim and CreateToken() handles the rest. A string representation of the SWTToken is returned by the SignedToken property. I'll talk about producing a signed token a little later in this section.

Figure 5 also shows the code to request a token from the ACS using the WebClient type—a wrapper around the HttpWebRequest for generating HTTP requests. Your job is to send an HTTP POST to the ACS issuer Uri (TokenIssuerUri) passing the form-encoded parameters discussed earlier: wrap_assertion_format, wrap_assertion and wrap_scope. If the request is poorly formatted, you'll get an exception with HTTP 400 response (bad request), and if the request is denied by the ACS you'll get an exception with HTTP 401 (access denied). A successful response returns a byte array with two form-encoded values: wrap_access_token and wrap_access_token_expires_in. The first value represents the token you will need to authenticate to the service. You can hydrate a SWTToken instance from this response as shown at the bottom of Figure 5 and use the SignedToken property to use in the Authorization header when calling the service.



When hydrating a SWTToken instance from the ACS response, the elements of the signed token string are used to populate properties of the SWTToken—but this may be overkill if you are only planning to use the signed token string to pass to services. In that case, I also included a static member to simply process the ACS response and return the signed token string. Thus, the following are alternatives to processing the ACS response:

string tokenString = SWTToken.GetSignedTokenString(responseBytes);<br>SWTToken token = new SWTToken(responseBytes);


Creating a Signed SWT Token
The SWTToken type exposes a SignedToken property which produces a signed SWT token string. The internals of the class break this down into some reusable methods, but Figure 6 shows the SWTToken class properties and functionality used to produce the result—in a manner consistent with the AppFabric SDK samples. Before producing the token, the NameValueCollection carrying claims must be de-normalized so that there are no duplicate claim types. For example, if multiple permission claims exist, they must be put into a comma-delimited string. Once the claims are formatted, the StringBuilder first produces the unsigned SWT token, which is a list for form-encoded name/value pairs including the claims, the issuer, the audience, and the expiry for the token (note that each value is encoded). An HMAC signature is then produced from this unsigned token string and added as another form-encoded parameter at the end of the unsigned token string.

Authentication to the Service
After successfully retrieving a signed token from the ACS the client passes this token in the HTTP Authorization header as follows:

Authorization: WRAP access_token=\\{signed token\\}


If you are using a WCF proxy, you achieve this by adding an outgoing request header within a new OperationContext for the call. The following code, for example, illustrates how the code looks for a REST-based WCF proxy created with WebChannelFactory<T> . You can add the header using the WebOperationContext:

WebChannelFactory<ITodoListService> factory = new WebChannelFactory<ITodoListService>("");<br>proxy = factory.CreateChannel();<br>using (new OperationContextScope(proxy as IContextChannel))\\{<br>  WebOperationContext.Current.OutgoingRequest.Headers.Add(<br>HttpRequestHeader.Authorization, token.SignedToken);<br>  this._TodoItems = new ObservableCollection<TodoItem>(proxy.GetItems());<br>\\}<br>


If you can't use a WCF proxy for some reason, such as in a Silverlight application, you can use the WebClient type (shown earlier) or the HttpWebRequest  type (a lower-level object model for dealing with HTTP requests) and add the Authorization header before sending the message. The obvious downside to these alternatives is the extra work required to handle complex type serialization—something the WCF proxy does for you.

Note: The ACS targets REST-based service and other web resources that don't have a rich security model available to them. That said, that doesn't mean that you can't request a token for a SOAP-based service as well and add the authorization header to outgoing requests. You can also use an alternate HTTP header if for some reason the Authorization header was already in use for another purpose. In that case, the service code must know which header will carry the SWT.

Authorizing Access at the Service
WCF services usually rely on binding configuration and service behaviors to determine how the service will be secured. The binding configuration indicates the type of security to be used (transport or message security) and the type of credentials to be provided by the client. The service behavior indicates how credentials should be authenticated and authorize. To process tokens issued by the ACS WCF must process a token passed in the HTTP Authorization header and process the string as a SWT token. This means a few things to the setup for your WCF services:

  • Set the binding security mode to None or Transport since we won't be using any built-in security mechanism.
  • Set transport security credential type to None since we aren't expecting one of the predefined credential types.
  • Install a custom ServiceAuthorizationManager to process the incoming Authorization header and gather the claims presented in the SWT.
  • Authorize access based on the claims.



To support this model, I created a custom ServiceAuthorizationManager—but since I'm a big fan of WIF for claims-based security implementations, I based this component on the IdentityModelServiceAuthorizationManager—which means that WIF must also be enabled for the service. Figure 7 shows the implementation of this custom type, SWTAuthorizationManager. The CheckAccess() override grabs the incoming Authorization header, hydrates a SWTToken instance from its value, and uses the SWTTokenHandler to validate the token before processing its claims.

Once validated, the claims are converted to WIF claims and a ClaimsPrincipal is constructed for the authorization context. Ultimately this ClaimsPrincipal will be attached to the request thread and can be used to authorize access.

Since this type is overriding the default behavior of the IdentityModelServiceAuthorizationManager, the code invokes the configured ClaimsAuthenticationManager and ClaimsAuthorizationManager so that you can hook the usual extensibility points to authenticate and authorize access. For example, you can implement a custom ClaimAuthenticationManager to modify the claimsPrincipal to be attached to the request thread, or you can implement a custom ClaimsAuthorizationManager to perform centralized access checks like that shown in Figure 8. When centralizing authorization checks from a custom ClaimsAuthorizationManager, you'll look at the claims supplied in the ClaimsIdentity for the context and implement your own heuristics for authorization.

An alternative to centralized claims authorization is to explicitly check claims at each service operation. You can use the PrincipalPermissionAttribute to decorate each service operation, for example, and demand a specific Role claim:

\\[PrincipalPermission(SecurityAction.Demand, Role = "Delete")\\]<br>public void DeleteItem(string id)<br>\\{…\\}


This requires the ClaimsIdentity to use a specific claim type as the role claim type, in this case the "Permission" claim type. The following CustomClaimsAuthenticationManager sets the RoleClaimType property for this application scenario:

public class CustomClaimsAuthenticationManager : ClaimsAuthenticationManager<br>\\{<br>  public override IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)<br>  \\{<br>    ClaimsIdentity identity = incomingPrincipal.Identity as ClaimsIdentity;<br>    identity.RoleClaimType = "Permission";<br>    return incomingPrincipal;<br>  \\}<br>\\}


Until Next Time
I'll be talking about the ACS in upcoming columns, but this article should get you well on your way to securing WCF services with the ACS. Download the code at www.dasblonde.net/downloads/acs/acswcfcomponents.zip and have some fun!


Michele Leroux Bustamante (mlb@idesign.net) is chief architect for IDesign, chief security architect for BiTKOO, a Microsoft Regional Director for San Diego, and a Microsoft MVP for Connected Systems. Her latest book is Learning WCF (O'Reilly), and she blogs at www.dasblonde.net.