Geeks With Blogs
Yossi Dahan

Briefly back on my STS work -

Our STS implementation can already replace the authentication implementation of most of our applications; naturally we can’t do that just yet, given that the Geneva-framework has not been released yet, but all of my tests are quite positive so we’re just waiting for the opportunity to start using it.

However, so far, we  were not in a position to replace the authorisation mechanism, not easily anyway, and that’s something that was on my list for some time now.

The STS provides a list of claims, which the applications can relatively easily access via code, as many samples show, and this proves very useful; application can investigate various claims about a user and drive their functionality from that.

It does mean, though, that the applications need to change to support this new claims based mode for authorisation, which is not something we can just assume we would be able to do; as a start, we just want to achieve an in-place replacement for our current authorisation logic.

Most of our web apps currently use ASP.net membership and roles and so they extensively use ‘IsInRole’ checks to figure out user authorisation and drive the application behaviour, to start with, we had to hook to that mechanism.

Luckily the Geveva framework has a relatively good support for exactly this need - , out of the box, it would convert any claims of the Microsoft role namespace (‘http://schemas.microsoft.com/ws/2008/06/identity/claims/role’) to roles; so – if a token included a claim of this type with a value of ‘Manager’, a call to HttpContext.Current.User.IsInRole(“Manager”) would return true.

And so I made sure my STS adds any roles with the correct claim type, very easy.

However – this is very Microsoft centric. what about all those claims that come from systems that don’t follow Microsoft’s approach? (how dare they!) ? and what about us wanting to have our own claims, using our own types, some matching roles (while others may not…) -

Well – we needed a way to map any claims to ms-role claims before the Geneva framework does its bit.

As is often the case - Dominick Baier was most helpful in posting on exactly that, and so, following his example, I created my RoleClaimsMapper -

    public class RoleClaimMapper : ClaimsAuthenticationManager
    {
        public override IClaimsPrincipal Authenticate(string endpointUri, IClaimsPrincipal incomingPrincipal)
        {
            //load configuration section for component
            RoleClaimsMapperConfigurationSection config = 
                (RoleClaimsMapperConfigurationSection)ConfigurationManager.GetSection("RoleClaimsMapper");
            //create a collection of claim types and populate from configuratoin
            List<string> claimsToMap = new List<string>(config.RoleClaims.Count);
            foreach (RoleClaimConfigurationElement claimElement in config.RoleClaims)
                claimsToMap.Add(claimElement.ClaimType);
                
            //loop on all identities, we really only expect one, but can easily support multiple.
            foreach (IClaimsIdentity identity in incomingPrincipal.Identities)
            {
                //extract the claims that we need to map (matching the configured list of claims)
                IEnumerable<Claim> roleClaims = 
                    identity.Claims.Where<Claim>(c => claimsToMap.Contains(c.ClaimType));
                //now create a role claim (using the MS role claim type) for each claim found; 
                //need to keep this outside claim loop so we don't modify the collection while iterating
                List<Claim> claimsToAdd = new List<Claim>(roleClaims.Count()); 
                foreach (Claim claim in roleClaims)
                    claimsToAdd.Add(new Claim(Microsoft.IdentityModel.Claims.ClaimTypes.Role, claim.Value,claim.ValueType,"local",claim.Issuer));
                //add new claims to current identity
                identity.Claims.AddRange(claimsToAdd);
            }

            return incomingPrincipal;
        }
    }

I then configured my authentication manager with the framework -

<microsoft.identityModel>
    <claimsAuthenticationManager type="RoleClaimMapper,Identity.Utilities" />
  

and added my bit of custom configuration

  <RoleClaimsMapper>
    <RoleClaims>
      <add Type="http://someDomain.com/identity/claims/SomeRole"/>
      <add Type="http://someDomain.com/identity/claims/AnotherRole"/>
    </RoleClaims>
  </RoleClaimsMapper>

As you can see this code would take a list of claim types from configuration, and map all claims of these types to roles, adding them to the identity’s claims collection using the required claim type (leaving the original claim intact), and voila – when the app executes it can check the roles, corresponding to the values supplied in my custom claims using -

HttpContext.Current.User.IsInRole(“[custom claim value"]”);
Very nice indeed!

UPDATE: Dominic’s comment on this post  had indirectly suggested an even cleaner solution; instead of duplicating the claims, I can add the claim types I have as roles to each identity’s RoleClaimTypes collection; this achieves the same result in a much cleaner way, here is the updated function -

        public override Microsoft.IdentityModel.Claims.IClaimsPrincipal Authenticate(string endpointUri, Microsoft.IdentityModel.Claims.IClaimsPrincipal incomingPrincipal)
        {
            //load configuration section for component
            RoleClaimsMapperConfigurationSection config = 
                (RoleClaimsMapperConfigurationSection)ConfigurationManager.GetSection("RoleClaimsMapper");
                
            //loop on all identities, we really only expect one, but can easily support multiple.
            foreach (IClaimsIdentity identity in incomingPrincipal.Identities)
                //for each identity, add all the claim types that are role claim types.
                foreach (RoleClaimConfigurationElement claimElement in config.RoleClaims)
                    identity.RoleClaimTypes.Add(claimElement.ClaimType);

            return incomingPrincipal;
        }
Posted on Wednesday, April 1, 2009 8:34 AM Geneva , Federated Identity | Back to top


Comments on this post: RoleClaimsMapper for the Geneva Framework

# re: RoleClaimsMapper for the Geneva Framework
Requesting Gravatar...
I guess the preferred approach would be to populate the RoleClaimTypes property on IClaimsIdentity with the claims that represent roles.

There is currently no clear way to set this i think. In ASP.NET this could be done by a module though.

Hopefully this will get easier in the future
Left by Dominick on Apr 01, 2009 5:54 PM

Your comment:
 (will show your gravatar)


Copyright © Yossi Dahan | Powered by: GeeksWithBlogs.net | Join free