Identity in .NET 4.5–Part 2: Claims Transformation in ASP.NET (Beta 1)

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).

Update: Per a conversation I had yesterday, I want to add some bits of information here. Claims transformation has a broader scope than what I describe above. In general claims transformation is the process of turning one identity into a different one by modifying claims. This could be done by creating new claims based on input claims, by passing through certain claims, or by removing non relevant input claims. Claims transformation can take place at various levels, above I describe application local transformation. Transformation typically also takes place in security token services, e.g in an IdP where “bootstrap” credentials are used to create an access token, or in R-STSes where input tokens (from federated parties) are transformed to output tokens (for applications).

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

This entry was posted in .NET Security, IdentityModel. Bookmark the permalink.

18 Responses to Identity in .NET 4.5–Part 2: Claims Transformation in ASP.NET (Beta 1)

  1. kajbonfils says:

    Hi Dominic,

    I have seen your video on PluralSight, and it brought me longer in 2hrs than I have been able to get in a 2 days… Its really uphill to learn about this stuff…

    Anyways.. I tried to do your demo app, but I have a strange issue. It seems that for every request i make, the HttpModule above is called 4 times – each time with a different session id, causing the cookie to be overwritten – and then the data in my claims are not saved.

    Do you have any clues on why that is happening.

    And btw. you might wanna mention the HTTP module above in the Pluralsight video.. Its only because I could see something in your solution explorer that i was missing in my solution, that i found this part.

    Thanks.

  2. Kaj Bonfils says:

    I have no idea about what was going on, but I restarted my debugging session and the call only happened once as expected…. I have another strange thing going on though…lt seems that the fedAuth cookie is never saved on the client… I can see some other people have the same problem, but I haven’t been able to find a solution. Any clues?

    I think I will try to make a clean solution and test it out.maybe something in my existing app is teasing me.

    Cheers, kaj

    • The cookieHandler config section allows to configure persistent session cookies.

      • kajbonfils says:

        Thanks, it solved it.

        I added the following section to web.config:

        and then

        Its a little hard to do this, as the documentation on msdn has little or no exaples yet.

        Do you have any links to in dept resourses (Except your own blog of course)? I bought the “Programming WIF” by Vitorrio Bertocci (http://www.amazon.com/Programming-Windows-Identity-Foundation-Dev/dp/0735627185) on kindle yesterday and started on page 1… But it only covers v. wif for .net 4.

      • kajbonfils says:

        Hmmm. WordPress killed my code…
        <configSections>
        <section name=”system.identityModel.services” type=”System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089″/>
        </configSections>

        <system.identityModel.services>
        <federationConfiguration >
        <cookieHandler mode=”Default” requireSsl=”false” />
        </federationConfiguration>
        </system.identityModel.services>

  3. Devaron says:

    I’m noticing the same thing. After I authenticate, the ContainsSessionTokenCookie(context.Request.Cookies) always returns false causing my ClaimsIndentity to be transformed on each Request. I have VS 2012 RC.

    • Can you confirm that the session cookie got send by your browser? Are you on SSL?

      • Devaron says:

        I’m not running over SSL. I’m using Fiddler and I see that I get a Cookie for my Web App (based on my Forms Auth setting in the Config). Also, I’m using ASP.NET Membership Provider to authenticate. I then use your code from PluralSite to add ClaimsIdentity/Claims stuff. What I did notice in Fiddler is that other Cookies were trying to be set (FedAuth and FedAuth1). But, they never stuck. Meaning on the future Requests I did not seem them in the Header. Only my Form Auth Cookie from my Web.config was being sent. I’m wondering if there is a conflict in the Cookies, since the FedAuth and FedAuth1 Cookies are for the same Domain (in my case – empty because I’m running in Cassini).

      • Devaron says:

        I added the configuration from the post above by kajbonfils and all is working now. The FedAuth/FedAuth1 Cookies are now being sent on subsequent requests after User logs in. Very cool stuff. Great videos on the PluralSite.

  4. I am not aware of other resources for .NET 4.5

  5. Pavlos Polianidis says:

    Hi Dominick,

    I have a question which is think is relevant to this topic, and i wonder if you could help me.
    There is an issue that i’ve come across recently which i really cannot resolve. I have a web application that uses Federated claims-based authentication using the Identity Server as the STS. I have a custom implementation of the ClaimsAuthenitcationManager where i go all the custom claims principal transformation. I’ve been testing my app on IISExpress and everything used to work fine; The authenticate methods was being invoked by FAM; However, once i deployed the application on a virtual machine using the IIS, that method is not being fired anymore. I honestly, don’t know what I’ve done wrong. I wonder if you know anything about that.

    Cheers,
    Pavlos

  6. Da_Wolf says:

    Had the same issues as kajbonfils. The system.identityModel.services config part worked out for me thanks kajbonfils!

  7. fel0niousmonk says:

    Hi Dominick,

    I’m now going down this path to cache our user’s principals after successful login via Windows Auth, but doing this has caused another problem: Authorize() and IsInRole can now no-longer be used to check for membership in DOMAIN\GROUP (presumably using a friendly name – I could very well use a SID, since those are what get populated in the claims).

    This is frustrating because it seems there is no happy medium to using claims with Windows auth WHILE supplementing those default Windows claims with custom ones AND wanting to cache those custom claims/principal.

    Am I missing something, or is this a trade-off we’ll have to live with? And, if we wish to support domain group friendly names, we’ll have to query AD and add those names as additional custom claims at the same time we add the other custom ones?

    TIA

    • You could translate the group SIDs to the “display names” before caching them in the principal. Simply call the Translate method on WindowsIdentity.Groups for that.

  8. not sure why, but:

    FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(ctx.Request.Cookies)

    if contains cookie, it contains not transformed one.

    I’m not sure if this is web config setting but if it is I’m not sure which one, as cookieHandler is set example the same as kajbonfils had.

    removing this check for contains will always transform my principal – which is not thing I want to do :(

    any ideas how this can be solved?

    thanks

  9. christian says:

    There is 2 problems with this code:
    you have to limit the execution of the module only to MVC page and not images

    you cannot add Claims to the incomingPrincipal. you have to create a other principal, inject the identity :
    ClaimsPrincipal newPrincipal = new ClaimsPrincipal(((ClaimsIdentity)incomingPrincipal.Identity));
    then return this new principal.
    when the user is not authenticate, you can return the old incomingprincipal

    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
    if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
    {
    ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, “User”));
    ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(CustomClaimTypes.Messenger, “ImportantMessenger”));
    ClaimsPrincipal newPrincipal = new ClaimsPrincipal(((ClaimsIdentity)incomingPrincipal.Identity));
    return newPrincipal;

    }
    return incomingPrincipal;

    }

Leave a Reply to Dominick Baier Cancel 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 )

Facebook photo

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

Connecting to %s