ASP.NET WebAPI Security 3: Extensible Authentication Framework

In my last post, I described the identity architecture of ASP.NET Web API. The short version was, that Web API (beta 1) does not really have an authentication system on its own, but inherits the client security context from its host. This is fine in many situations (e.g. AJAX style callbacks with an already established logon session). But there are many cases where you don’t use the containing web application for authentication, but need to do it yourself. Examples of that would be token based authentication and clients that don’t run in the context of the web application (e.g. desktop clients / mobile).

Since Web API provides a nice extensibility model, it is easy to implement whatever security framework you want on top of it. My design goals were:

  • Easy to use.
  • Extensible.
  • Claims-based.

..and of course, this should always behave the same, regardless of the hosting environment. In the rest of the post I am outlining some of the bits and pieces, So you know what you are dealing with, in case you want to try the code.

At the very heart…
is a so called message handler. This is a Web API extensibility point that gets to see (and modify if needed) all incoming and outgoing requests. Handlers run after the conversion from host to Web API, which means that handler code deals with HttpRequestMessage and HttpResponseMessage. See Pedro’s post for more information on the processing pipeline.

This handler requires a configuration object for initialization. Currently this is very simple, it contains:

  • Settings for the various authentication and credential types
  • Settings for claims transformation
  • Ability to block identity inheritance from host

The most important part here is the credential type support, but I will come back to that later.

The logic of the message handler is simple:

  1. Look at the incoming request.
  2. If the request contains an authorization header, try to authenticate the client.
    1. If this is successful, create a claims principal and populate the usual places.
    2. If not, return a 401 status code and set the Www-Authenticate header.
  3. Look at outgoing response, if the status code is 401, set the Www-Authenticate header.

Credential type support
Under the covers I use the WIF security token handler infrastructure to validate credentials and to turn security tokens into claims. The idea is simple: an authorization header consists of two pieces: the schema and the actual “token”. My configuration object allows to associate a security token handler with a scheme. This way you only need to implement support for a specific credential type, and map that to the incoming scheme value. The current version supports HTTP Basic Authentication as well as SAML and SWT tokens.

(I needed to do some surgery on the standard security token handlers, since WIF does not directly support string-ified tokens. The next version of .NET will fix that, and the code should become simpler then).

You can e.g. use this code to hook up a username/password handler to the Basic scheme (the default scheme name for Basic Authentication).

config.Handler.AddBasicAuthenticationHandler(
(username, password) => username == password);

You simply have to provide a password validation function which could of course point back to your existing password library or e.g. membership.

The following code maps a token handler for Simple Web Tokens (SWT) to the Bearer scheme (the currently favoured scheme name for OAuth2). You simply have to specify the issuer name, realm and shared signature key:

config.Handler.AddSimpleWebTokenHandler(
   
"Bearer"
,
   
http://identity.thinktecture.com/trust
,
   
Constants
.Realm,
   
"Dc9Mpi3jaaaUpBQpa/4R7XtUsa3D/ALSjTVvK8IUZbg=");

For certain integration scenarios it is very useful if your Web API can consume SAML tokens. This is also easily accomplishable. The following code uses the standard WIF API to configure the usual SAMLisms like issuer, audience, service certificate and certificate validation. Both SAML 1.1 and 2.0 are supported.

var registry = new ConfigurationBasedIssuerNameRegistry();
registry.AddTrustedIssuer(
"d1 c5 b1 25 97 d0 36 94 65 1c e2 64 fe 48 06 01 35 f7 bd db", "ADFS"
);

var adfsConfig = new SecurityTokenHandlerConfiguration
();
adfsConfig.AudienceRestriction.AllowedAudienceUris.Add(
new Uri(Constants
.Realm));
adfsConfig.IssuerNameRegistry = registry;
adfsConfig.CertificateValidator =
X509CertificateValidator
.None;

// token decryption (read from configuration section)
adfsConfig.ServiceTokenResolver =
FederatedAuthentication
.ServiceConfiguration.CreateAggregateTokenResolver();

config.Handler.AddSaml11SecurityTokenHandler(
"SAML", adfsConfig);

Claims Transformation
After successful authentication, if configured, the standard WIF ClaimsAuthenticationManager is called to run claims transformation and validation logic. This stage is used to transform the “technical” claims from the security token into application claims. You can either have a separate transformation logic, or share on e.g. with the containing web application. That’s just a matter of configuration.

Adding the authentication handler to a Web API application
In the spirit of Web API this is done in code, e.g. global.asax for web hosting:

protected void Application_Start()
{
   
AreaRegistration
.RegisterAllAreas();

    ConfigureApis(
GlobalConfiguration
.Configuration);
    RegisterGlobalFilters(
GlobalFilters
.Filters);
    RegisterRoutes(
RouteTable
.Routes);

   
BundleTable.Bundles.RegisterTemplateBundles();
}
private void ConfigureApis(HttpConfiguration configuration)
{
    configuration.MessageHandlers.Add(
new AuthenticationHandler
(ConfigureAuthentication()));
}
private AuthenticationConfiguration ConfigureAuthentication()
{
   
var config = new AuthenticationConfiguration
    {
       
// sample claims transformation for consultants sample, comment out to see raw claims
        ClaimsAuthenticationManager = new ApiClaimsTransformer
(),

       
// value of the www-authenticate header,
// if not set, the first scheme added to the handler collection is used
        DefaultAuthenticationScheme = "Basic"
    };


   
// add token handlers - see above

    return config;
}

You can find the full source code and some samples here.

In the next post I will describe some of the samples in the download, and then move on to authorization.

HTH

This entry was posted in IdentityModel, WebAPI. Bookmark the permalink.

4 Responses to ASP.NET WebAPI Security 3: Extensible Authentication Framework

  1. Pingback: Thinktecture.IdentityModel and ASP.NET Web API | www.leastprivilege.com

  2. atconway says:

    Wow, I really would like the full code for this *specific* sample for this page if there is an updated link. Could you please provide an updated link for this sample because the one listed is broken? Thanks!

  3. atconway says:

    Perfect, thank you.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s