Introduction to Claims based security in .NET4.5 with C# Part 3: claims transformation

An important feature of ClaimsPrincipal in .NET4.5 is the unification of different credential formats. ‘Unification’ means that all credential types can be handled with the help of Claims. The application doesn’t need to know exactly how the Claims were issued, i.e. which authentication type was used to issue the claims. The only thing we care about is the claims collection.

There’s a pluggable infrastructure in .NET4.5 which understands these protocols and knows how to turn them into Claims. There’s built-in support for the most common protocols, such as Windows, Forms, SSL, SAML, which all issue their credentials in different formats. They can be turned into claims using an object called the SecurityTokenHandler. One of the functions of this object is to translate one format into another.

This object has methods for:

  • Reading tokens
  • Validating tokens
  • Writing tokens
  • Determining token types

The first step is usually to read the incoming tokens. The various overloaded ReadToken methods return a SecurityToken object. The ValidateToken method accepts a SecurityToken and returns a collection of ClaimsIdentity objects. You can use this object to create your own mechanism to create tokens, a so called Security Token Service (STS), in which case methods, such as WriteToken and CreateToken will be useful. There are ready-made STSs, such as the Active Directory Federation Service (ADFS) that have the function of authenticating a user and issuing claims that describe the user. .NET4.5 includes several derived types of the SecurityTokenHandler object, such as:

  • KerberosSecurityTokenHandler
  • RsaSecurityTokenHandler
  • SamlSecurityTokenHandler
  • UserNameSecurityTokenHandler

…and many more. If the built-in types do not suit your needs then you can always create your own class by deriving from the SecurityTokenHandler object and implement the methods that you need: ReadToken and ValidateToken if you only want to read and validate tokens. Indeed, you may not even have to implement your own type this way. If all you need is an X509 certificate handler that’s slightly different from the built-in X509SecurityTokenHandler then derive from this object instead of the SecurityTokenHandler object. This approach will save you a lot of time.

The processing pipeline of claims is as follows:

  1. Your application receives the token in some format: XML, Binary or text
  2. The token handling mechanism, i.e. the SecurityTokenHandler kicks in and deserialises the token using the ReadToken method
  3. The same object will also validate the token using the ValidateToken method – this step results in a ClaimsPrincipal object
  4. The resulting ClaimsPrincipal is transformed according to your needs

Why do we need the last step? Actually it is an optional step. If the ClaimsPrincipal from step 3 perfectly meets your authentication and authorisation needs then no more transformation is necessary. If the token was issued by ADFS then it will include all the claims that are usually available in Windows: the Name claim and the group SIDs. In a common web-based log-in scenario the only claim available may be the user name. If you need to check other claims during your authorisation process then you’ll need to ‘dress up’ the ClaimsPrincipal from step 3 using some claims transformation technique.

It is also possible that the claims collection you receive from step 3 is too large. Then you may even have to remove the unnecessary claims before passing them on to your authorisation process. It is recommended to include only those claims that are absolutely necessary for your application – not more, not less.

Claims transformation demo

Let’s take a look at how the claims can be transformed in C#.

Start Visual Studio 2012 and create a new Console application with .NET4.5 as the underlying framework. We will pretend that our application receives a WindowsPrincipal object whose claims collection needs to be transformed.

Create the following skeleton in Main.cs:

static void Main(string[] args)
        {
            SetCurrentPrincipal();
            UseCurrentPrincipal();
        }

        private static void UseCurrentPrincipal()
        {

        }

        private static void SetCurrentPrincipal()
        {
            Thread.CurrentPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
        }

In Part 2 of the blog posts on Claims we saw that WindowsPrincipal includes a lot of group SID claims. It is unlikely that your application will need them all. In order to transform the claims to fit our needs we need a class that derives from an object called ClaimsAuthenticationManager in the System.Security.Claims namespace. Add a class called CustomClaimsTransformer and add a reference to System.IdentityModel.dll, otherwise the ClaimsAuthenticationManager object will not be found:

public class CustomClaimsTransformer : ClaimsAuthenticationManager
    {
    }

The method that we’ll need to override is called Authenticate:

public class CustomClaimsTransformer : ClaimsAuthenticationManager
    {
        public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            return base.Authenticate(resourceName, incomingPrincipal);
        }
    }

The first parameter, i.e. ‘resourceName’ gives us the opportunity to specify some type of context. E.g. in an ASP.NET application we can pass in the URL the user tries to access. The transformation logic may depend on the resource type.

Note that the method accepts a ClaimsPrincipal and also returns a ClaimsPrincipal. You can inspect the claims collection of the ‘incomingPrincipal’ object, add/remove claims directly in it and return the transformed object. The recommended way, however, is to build a brand new ClaimsPrincipal object and fill its claims collection with the necessary claim types and values. You can remove the call to the base.Authenticate method. The application will not compile as the method doesn’t return any objects but we’ll fix that soon.

The first step in our custom implementation is to validate the claims. In this step you can check whether all necessary initial claim types have come in, they are in the required format and were issued by a trusted issuer. Here we’ll only check if the Name claim is null or empty:

            //validate name claim
            string nameClaimValue = incomingPrincipal.Identity.Name;

            if (string.IsNullOrEmpty(nameClaimValue))
            {
                throw new SecurityException("A user with no name???");
            }

The next step is to build the ClaimsPrincipal and this is entirely up to you and your authentication/authorisation needs. Example: you can look at the SIDs in the WindowsPrincipal and convert them to your custom permissions. Here we’ll simulate a database lookup based on the name claim. Add the following return statement to the Authenticate method:

return CreatePrincipal(nameClaimValue);

…where the CreatePrincipal method looks as follows:

        private ClaimsPrincipal CreatePrincipal(string userName)
        {
            bool likesJavaToo = false;

            if (userName.IndexOf("andras", StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                likesJavaToo = true;
            }

            List<Claim> claimsCollection = new List<Claim>()
            {
                new Claim(ClaimTypes.Name, userName)
                , new Claim("http://www.mysite.com/likesjavatoo", likesJavaToo.ToString())
            };

            return new ClaimsPrincipal(new ClaimsIdentity(claimsCollection, "Custom"));
        }

We’re only interested in two claims: the name claim and whether the user likes writing Java as well. Instead of the userName.IndexOf call we would of course have some database lookup to see who actually likes Java. Then we build our claims collection and pass it in the ClaimsPrincipal through the ClaimsIdentity object. “Custom” is the authentication type description, can be whatever value, it’s up to you. Recall from Part 1 of the blog posts on Claims that you need to set the authentication type to some value in order to turn this Identity into an authenticated one. It’s not enough for the user to have a name, you need to provide the authentication type as well.

You need to register your custom claims transformer in app.config. Before you do that add a reference to the System.identitymodel.services.dll. In app.config insert a new config section as follows:

<configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
  </configSections>

You need to register the custom claims transformer as follows:

  <system.identityModel>
    <identityConfiguration>
      <claimsAuthenticationManager type="ClaimsTransformationDemo.CustomClaimsTransformer,ClaimsTransformationDemo"/>
    </identityConfiguration>
  </system.identityModel>

The type value may differ in your case depending on the name you gave your project. You’ll need to give the fully qualified name of the class, i.e. namespace and the class name and then the assembly name after the comma.

In order to invoke the transformation logic we don’t set the incoming WindowsPrincipal object to the current principal of the thread as we currently do it in SetCurrentPrincipal(). We need to get hold of the incoming principal, pass it in our custom Authenticate method, get the transformed ClaimsPrincipal object and set it to the current principal of the thread. This can be done in 2 lines of code but the transformer invocation call is quite long:

private static void SetCurrentPrincipal()
        {
            WindowsPrincipal incomingPrincipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            Thread.CurrentPrincipal = FederatedAuthentication.FederationConfiguration.IdentityConfiguration
                .ClaimsAuthenticationManager.Authenticate("none", incomingPrincipal);
        }

You will need to import the System.IdentityModel.Services namespace where the FederatedAuthentication object is located. We don’t care about the resource name so we pass in a “none”. Set a breakpoint at the Authenticate method of the CustomClaimsTransformer class and run the application. You may receive an exception saying that you’ll need a reference to the System.Web assembly, so do exactly as it says. So, run the application with the breakpoint at Authenticate and see if it is invoked.

If all went well then code execution is stopped at the breakpoint meaning that your custom claims transformation logic has successfully been registered and invoked. Step through the code with F11 and check that each line executes as expected. Inspect the contents of Thread.CurrentPrincipal and you’ll see that it has two claims; the name claim and our custom ‘likesjavatoo’ claim:

Claims transformation success

From this point on our application will not see all the ‘noise’ in the claims collection, i.e. all the unnecessary Windows-related claims. It will only see the ones that are needed.

We discussed how to populate an incoming Claims collection to one that fits our authentication and authorisation needs further down in the code. In the next post we’ll see how to use the claims to authorise access to certain parts of the application.

You can view the list of posts on Security and Cryptography here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

19 Responses to Introduction to Claims based security in .NET4.5 with C# Part 3: claims transformation

  1. Aaron says:

    Thanks for your hard work on this series. Well written and much appreciated!

  2. Rick Beery says:

    Nice series of articles! Thanks.

    I just wanted to add one note when adding the ; that i It must be the first child of the root element. I was getting the following error, “An unhandled exception of type ‘System.Configuration.ConfigurationErrorsException’ occurred in System.Configuration.dll” before I discovered that out.

    • Andras Nemes says:

      Hi Rick, thanks. WordPress may have removed some bits from your comment. I don’t see what needs to be the first child. I don’t understand the “the ; that i lt must be” part.
      //Andras

  3. Irina says:

    Thanks a lot. Got the same error as Rick. He means configSections must be the first child of configuration element.

  4. Reza says:

    Hi Andras, Thnx for ur great Tuts. I’ve got same error

    An unhandled exception of type ‘System.Configuration.ConfigurationErrorsException’ occurred in System.Configuration.dll

    Additional information: The value of the property ‘type’ cannot be parsed. The error is: The type ‘ClaimsTransformationDemo.CustomClaimsTransformer,ClaimsTransformationDemo’ cannot be resolved. Please verify the spelling is correct or that the full type name is provided.

  5. chi.le says:

    I am having the same error as Rez (as seen below). I checked, double, and triple and my class full class name (namespaceName.class,assemblyName) and believe it to be correct. I am at a loss. Any ideas out there?

    Error Below

    The value of the property ‘type’ cannot be parsed. The error is: The type ‘ConsoleApplication3.CustomClaimsTransformer,ConsoleApplication3’ cannot be resolved. Please verify the spelling is correct or that the full type name is provided.

  6. krishnamohan says:

    Hi is there any possibility that i can pass windows identity of one user from onemachine to another machine… plzz reply… i need it very badly……….

  7. Asif Sehzaad says:

    I am hvaing some problems with the
    FederatedAuthentication.FederationConfiguration

    Can you please post the source code somewhere for reference

  8. This is a most comprehensive demo, but I am having trouble, which I think is down to my app.config, which looks like

    The application fails at :

    Thread.CurrentPrincipal = FederatedAuthentication.FederationConfiguration.IdentityConfiguration
    .ClaimsAuthenticationManager.Authenticate(“none”, incomingPrincipal);

    with the following error

    The value of the property ‘type’ cannot be parsed. The error is: The type ‘ClaimsConsoleApp2.CustomClaimsTransformer,ClaimsConsoleApp2’ cannot be resolved.

    I think this means that I have not correctly registed “ClaimsConsoleApp2.CustomClaimsTransformer”, but I am not sure how to correct this

    Thanks in advance

    • Andras Nemes says:

      Have you registered the authentication manager correctly? Do your values point to the correct namespace and class?
      //Andras

      • Thank you for the quick response. I am reasonable sure I havent registered this properly ! A link to a complete working app.config, with a note of how it maps to the namespace would be really useful. Thanks again

        *Regards Richard *

        *Richard Scannell**Senior Analyst Programmer* *Systems Development and Analysis* *Information Assets* *Resources Group* *Warwickshire County Council* *Tel: (01926 41) 2121* Your ICT Services Catalogue will be available Anytime, Anywhere and on Any device

        On 1 May 2015 at 11:27, Exercises in .NET with Andras Nemes wrote:

        > Andras Nemes commented: “Have you registered the authentication manager > correctly? Do your values point to the correct namespace and class? > //Andras”

      • Thank you for the quick response. I am reasonably sure I havent registered this properly & my original post had the app.config removed by wordpress . A link to a complete working app.config, with a note of how it maps to the namespace would be really useful. Thanks again

  9. … App Config was removed ! ,

    <?xml version=”1.0″ encoding=”utf-8″ ?>
    <configuration>
    <configSections>
    <section name=”system.identityModel” type=”System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089″/>

    <sectionGroup name=”applicationSettings”
    type=”System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ >
    <section name=”ClaimsConsoleApp2.Properties.Settings”
    type=”System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″
    requirePermission=”false” />
    </sectionGroup>
    </configSections>
    <startup>
    <supportedRuntime version=”v4.0″ sku=”.NETFramework,Version=v4.5″ />
    </startup>
    <system.identityModel>
    <identityConfiguration>
    <claimsAuthenticationManager type=”ClaimsConsoleApp2.CustomClaimsTransformer,ClaimsConsoleApp2″/>
    </identityConfiguration>
    </system.identityModel>
    </configuration>

  10. Problem fixed: I’d put the CustomClaimsTransformer inside the Program class Doh !! Thanks

  11. bnorth2014 says:

    I am confused. UseCurrentPrincipal() method is left empty at the beginning of the article and then a new version of SetCurrentPrincipal() method is shown in the end. Its somewhat confusing without explanation. But I’ll go over it again.

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

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: