Identity in .NET 4.5–Part 2: Claims Transformation in ASP.NET (Beta 1)
- by Your DisplayName here!
In my last post I described how every identity in .NET 4.5 is now claims-based. If
you are coming from WIF you might think, great – how do I transform those claims?
Sidebar: What is claims transformation?
One of the most essential features of WIF (and .NET 4.5) is the ability to
transform credentials (or tokens) to claims. During that process the “low level” token
details are turned into claims. An example would be a Windows token – it contains
things like the name of the user and to which groups he belongs to. That information
will be surfaced as claims of type Name and GroupSid. Forms users
will be represented as a Name claim (all the other claims that WIF provided
for FormsIdentity are gone in 4.5). The issue here is, that your applications
typically don’t care about those low level details, but rather about “what’s the purchase
limit of alice”. The process of turning the low level claims into application specific
ones is called claims transformation. In pre-claims times this would have been done
by a combination of Forms Authentication extensibility, role manager and maybe ASP.NET
profile. With claims transformation all your identity gathering code is in one place
(and the outcome can be cached in a single place as opposed to multiple ones).
The structural class to do claims transformation is called ClaimsAuthenticationManager.
This class has two purposes – first looking at the incoming (low level) principal
and making sure all required information about the user is present. This is your first
chance to reject a request. And second – modeling identity information in a way it
is relevant for the application (see also here).
This class gets called (when present) during the pipeline when using WS-Federation.
But not when using the standard .NET principals. I am not sure why – maybe because
it is beta 1. Anyhow, a number of people asked me about it, and the following is a
little HTTP module that brings that feature back in 4.5.
public class ClaimsTransformationHttpModule :
IHttpModule
{
public void Dispose()
{ }
public void Init(HttpApplication
context)
{
context.PostAuthenticateRequest += Context_PostAuthenticateRequest;
}
void Context_PostAuthenticateRequest(object sender, EventArgs e)
{
var context
= ((HttpApplication)sender).Context;
//
no need to call transformation if session already exists
if (FederatedAuthentication.SessionAuthenticationModule
!= null &&
FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(context.Request.Cookies))
{
return;
}
var transformer
=
FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
if (transformer
!= null)
{
var transformedPrincipal
= transformer.Authenticate(context.Request.RawUrl, context.User as ClaimsPrincipal);
context.User =
transformedPrincipal;
Thread.CurrentPrincipal
= transformedPrincipal;
}
}
}
HTH