image

Here there’s another (very) frequently asked question. I have the eerie sensation that I have already blogged about it, but a quick search did not yield any result post-WIF…. so here you go.
Say that I have a web app or a web API secured with Azure AD (or any other provider, really). Say that in my app I maintain attributes about my user, and I would find it handy to have such attributes exposed in form of claims, alongside the ones I receive from the trusted authority at authentication (nee token validation) time. How do I make it happen with Katana 3.x, OWIN’s implementation in ASP.NET4.6?

OpenId Connect

Easy. Let’s start with OpenID Connect (OIDC for brevity). The OIDC middleware graciously offer notifications at key stages of the validation pipeline. The last of those, SecurityTokenValidated, offers you the chance to modify the ClaimsIdentity obtained from the incoming token. Here there’s an example, where “RetrieveHairLenght” is a hypothetical function that queries by local DB for the desired attribute.

SecurityTokenValidated = (context) =>
{
    string userID = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
    Claim userHair =
      new Claim(http://mycustomclaims/hairlenght,
                RetrieveHairLenght(userID),
                ClaimValueTypes.Double, "LOCAL AUTHORITY");
    context.AuthenticationTicket.Identity.AddClaim(userHair);
    return Task.FromResult(0);
},

Once you have added that to your Notifications property of the options you initialize the OIDC middleware with, you’ll be able to read that claim from anywhere your app – just like any other “official” claim:

var userHair = ClaimsPrincipal.Current.FindFirst(http://mycustomclaims/hairlenght);

 

Preeeety neat. Note that this happens at token reception time, right before establishing the session. That means that whatever I/O you performed for retrieving your extra attributes will be done only once, which is good; it also means that the resulting custom claims will end up in your session cookie… and if you add too much stuff, the effects might not be good: performance hits, cookie clipping if you exceed the browser limits, and so on. Keep all those considerations in mind as you plan your augmentation strategy.

Web API

Now, say that you want to do the same for a web API.
If you are on ASP.NET 5, good news! You do exactly like the above (module the ClaimsPrincipal.Current part, topic for another post).

If you are on ASP.NET4.6 and Katana, that is a bit trickier. The web API middleware in Katana3.x does not have a very rich notifications pipeline. However you still have a mechanism for injecting your custom claims, it’s just a bit different. Given that this is a tad more exotic than just filling up a notification

app.UseWindowsAzureActiveDirectoryBearerAuthentication(
    new WindowsAzureActiveDirectoryBearerAuthenticationOptions
    {
        Audience = ConfigurationManager.AppSettings["ida:Audience"],
        Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
        Provider = new OAuthBearerAuthenticationProvider()
        {
            OnValidateIdentity = async context =>
            {
                context.Ticket.Identity.AddClaim(
                   new Claim(http://mycustomclaims/hairlenght, 
                                   RetrieveHairLenght(userID),                
                                   ClaimValueTypes.Double, 
                                   "LOCAL AUTHORITY");));
            }
        }
    });

OnValidateIdentity gives you a last chance of modifying the ClaimsIdentity before it gets passed to the app, in analogy to what you have seen for OIDC.

Note that in this case there is no cookie to remember the authority-issued claims and your custom attributes – the nature of the web API is that you’ll get the token at every. single. call.
You’ll probably be well served by some inmemory caching strategy, so that the call to RetrieveHairLenght does not have to query slow persistent storage all the time.

Short and sweet, especially because it’s 2:00am here Smile have fun with your custom claims!

 

Leave a Reply

Your email address will not be published. Required fields are marked *