Claims-based authentication in MVC4 with .NET4.5 C# part 3: claims based authorisation

In the previous post we discussed how to the save the authentication session so that we didn’t need to perform the same auth logic on every page request. In this post we will look at how authorisation can be performed using claims in an MVC project.

Introduction

There are two main approaches to authorisation in an ASP.NET web application: pipeline authorisation and Intra-app authorisation.

Pipeline auth means performing coarse grained, URL-based authorisation. You may require the presence of a valid auth header in every request that comes to your server. Or the authenticated user must be in a certain Role in order to reach a certain protected URL. The advantage with this approach is that authorisation happens very early in the application lifecycle so you can reject a request very early on. In this scenario you will typically have little info about the user and what resource they are trying to access but these can be enough to reject a large number of users.

An example of pipeline auth in our simple MVC4 web we’ve been working on this series can be found in CustomClaimsTransformer.Authenticate. This is the stage where you can check the presence of a certain claim that your auth logic absolutely must have in order to make an early decision. If it’s missing, then you may not care about what the user is trying to do, the request will be rejected.

Another example of pipeline auth comes from the good old ‘location’ elements in an ASP.NET web forms config where you could specify URL-based auth:

<location path="customers">
    <system.web>
      <authorization>
        <allow roles="IT"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>

This is an acceptable approach in web-forms projects where the URL has a close affinity to the project file system, i.e. the value of the ‘path’ attribute represents an .aspx file. In MVC /Customers will of course not lead to an aspx page called Customers. In MVC urls and resources are unlikely to have a one-to-one match. You don’t call physical files the same way as in a web-forms app. If the routing mechanism is changed then the path attribute will be meaningless. So all of a sudden people will have access to previously protected parts of your web app. Generally try to avoid this approach in an MVC application as it creates a tight coupling between the routing table and the project file structure.

Yet another example of pipeline auth is the ClaimsAuthorisationManager which can be registered in the web.config. This will sound familiar to you if you looked at the post on the very basics of claims. This is also a URL based approach, but it’s based on Claims and not Roles.

Intra-app auth on the other hand means fine-grained checks within your code logic. The benefit is that you have the chance to collect as much information as possible about the user and the resources they are trying to use. Then you can tweak your authorisation logic on a wider information basis. In this scenario you will have more info on the user and make your reject/accept decision later in the app lifecycle than in the Pipeline auth scenario.

A definite advantage of this approach is that it is not URL based any more so it is independent of the routing tables. You will have more knowledge about the authorisation domain because you’ll typically know exactly what claims the user holds and what they are trying to achieve on your site.

PrincipalPermission and ClaimsPrincipalPermission

You can follow a declarative approach using the ClaimsPrincipalPermission attribute or an imperative one within the method body. Either way you’ll work with Claims and not Roles as in the ‘old’ days with the well-known ‘Role=”IT”‘ and .IsInRole(“Admin”) type of checks:

[PrincipalPermission(SecurityAction.Demand, Role="IT")]

The old way of performing authorisation is not recommended now that we have access to claims in .NET4.5. Roles encouraged you to mix authorisation and business logic and they were limited to, well, Roles as the way of controlling access. However, you might have required more fine-grained control over your decision making. Then you ended up with specialised roles, like Admin, SuperAdmin, SuperSuperAdmin, MarketingOnThirdFloor etc. Decorating your methods with the PrincipalPermission attribute also disrupts unit testing as even the unit testing thread must have a User in the Role specified in the attribute. Also, if the current principal is not in the required group then an ugly security exception is thrown which you have to deal with somehow.

In this post we saw a detailed discussion on the ClaimsPrincipalPermission which replaces the PrincipalPermission. Here comes an example to refresh your memory:

[ClaimsPrincipalPermission(SecurityAction.Demand, Operation="Show", Resource="Code")]

In short: we don’t care which group or role the user is in any longer. This attribute describes the method it decorates. It involves a ‘Show’ operation on the ‘Code’ resource. If the current user wants to run this method then they better make sure that they have these claims. It will be the ClaimsAuthorizationManager that decides if the current principal is allowed to call the action ‘Show’ on the resource ‘Code’. The principal still must have certain claims, just like they had to be in a certain Role before. However, the authorisation logic is now separated out to a different part of the application. You can even have that logic in a web service on a different machine so that the auth logic can be handled entirely separately from your application.

Another benefit is the following: what constitutes a certain Role can change over time. What is ‘IT’? Who belongs to that group? So later on you may have to come back to every method with the attribute ‘Role=”IT”‘ and change it to e.g. “Geeks” because ‘IT’ has changed its definition at your company. On the other hand a method that has the function to ‘Show’ a resource called ‘Code’ will probably have that function over a long time, possible over the entire life time of the finalised production version of the application.

So, this attribute solves some of the problems with the PrincipalPermission. However, it does not solve all of them. It still gets in the way of unit testing and it still throws a SecurityException.

The Authorize attribute

The MVC ‘equivalent’ of the ClaimsPrincipal attribute is the Authorize attribute. It is still limited to roles:

[Authorize]
public ActionResult ShowMeTheCode()

[Authorize(Roles="IT")]
public ActionResult ShowMeTheCode()

It does not use the action/resource properties of the method and you still mix your auth logic with the ‘real’ application code leading to the same Separation of Concerns problem we mentioned above. However, this attribute is not invoked during unit testing and it does not throw Exceptions either. Instead, it returns a 404 which is a lot nicer way of dealing with unauthorised access.

We are only one step from the MVC4 claims-based authorisation nirvana. It would be great to have an Authorize attribute where you can specify the Resource and the Action just like in the case of ClaimsPrincipalPermission. You could derive from the existing Authorize attribute and implement this kind of logic there. The good news is that this has been done for you and it can be downloaded from NuGet. The NuGet package includes the imperative equivalent of the declarative attribute as well. So if you need to check if the user has access rights within a certain method, then there’s a claims-enabled solution in MVC4. We’ll use this attribute in the demo.

Demo

The initial steps of building the authorisation module have been outlined in this blog post. I will not repeat all of the details here again.

Open up the project where we left off in the previous blog post. If you remember then we included a CustomClaimsTransformer class to implement our own claims transformation logic. This is our claims based authentication module. We would like to extend the project to include authorisation as well.

First add a new class to the web project called CustomAuthorisationManager. It will need to derive from ClaimsAuthorizationManager in the System.Security.Claims namespace:

public class CustomAuthorisationManager : ClaimsAuthorizationManager
    {
        public override bool CheckAccess(AuthorizationContext context)
        {
            return base.CheckAccess(context);
        }
    }

Recall that you can extract the Resource, the Action and the Principal from the AuthorizationContext object parameter.

Now let’s say we want to make sure that only those with the name Andras who live in Sweden are allowed to view the code. I would do it as follows:

public override bool CheckAccess(AuthorizationContext context)
        {
            string resource = context.Resource.First().Value;
            string action = context.Action.First().Value;

            if (action == "Show" && resource == "Code")
            {
                bool livesInSweden = context.Principal.HasClaim(ClaimTypes.Country, "Sweden");
                bool isAndras = context.Principal.HasClaim(ClaimTypes.GivenName, "Andras");
                return isAndras && livesInSweden;
            }

            return false;
        }

Set a breakpoint at the first row of the method body, we’ll need it later.

This should be straightforward: we extract the Action and the Resource – note that there can be multiple values, hence the ‘First()’ – and then check where the user lives and what their given name is. If those claims are missing or are not set to the required values then we return false.

Next we have to register this class in the web.config under the claimsAuthenticationManager we registered in the previous part:

<system.identityModel>
    <identityConfiguration>
      <claimsAuthenticationManager type="ClaimsInMvc4.CustomClaimsTransformer,ClaimsInMvc4" />
      <claimsAuthorizationManager type="ClaimsInMvc4.CustomAuthorisationManager,ClaimsInMvc4"/>
    </identityConfiguration>
  </system.identityModel>

The type attribute is formatted as follows: [namespace.classname],[assembly].

Next we want to make sure that this logic is called when a protected action is called. We will try the claims-enabled version of the MVC4 Authorize attribute. Right-click ‘References’ and select ‘Manage NuGet Packages…’. Search for ‘Thinktecture’ and install the below package:

Thinktecture auth package NuGet

This package will give you access to a new attribute called ClaimsAuthorize where you can pass in the Action and Resource parameters.

Imagine that our About page includes some highly sensitive data that can only be viewed by the ones specified in CustomAuthorisationManager.CheckAccess. So let’s decorate the About action of the Home controller. Note that the attribute comes in two versions: one for MVC4 and one for WebAPI. If you haven’t heard of Web API, then it is a technology to build RESTful web services whose structure is very much based on MVC. You can read more about it here.

Reference the version for Mvc:

Two versions of claims authorize

…and decorate the About action as follows:

[ClaimsAuthorize("Show", "Code")]
        public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";

            return View();
        }

This is telling us that the About action will perform a ‘Show’ action on the resource called ‘Code’.

Run the application now. Click on the ‘About’ link without logging in first. You should be redirected to the Log-in page. Enter the username and password and press the ‘Log in’ button. If everything went well then code execution should stop at our breakpoint within CustomAuthorisationManager.CheckAccess. Step through the method using F11 to see what happens. You can even inspect the AuthorizationContext object in the Locals window to see what it contains:

AuthorizationContext object

If the logged on user has the correct claims then you should be redirected to the About page. I will here again stress the point of getting away from the traditional Roles based authorisation of ASP.NET. We are not dealing with Roles any longer. We do not care who is in which group. Instead we describe using the Action and Resource parameters of the ClaimsAuthorize attribute what the logged on user is trying to achieve on our website. Based on that information we can make a better decision using the claims of the user whether to allow or deny access. The auth logic is separated away from the ‘real’ application in a class on its own which is called automatically if it is registered in web.config. The auth logic can even be ‘outsourced’ to a web service which can even be the basis of a separate user management application.

You can specify multiple Resource values in the attribute as follows:

[ClaimsAuthorize("Show", "Code", "TvProgram", "Fireworks")]
        public ActionResult About()
        {
            ViewBag.Message = "Your app description page.";

            return View();
        }

…i.e. you just pass in the names of the Resources after the Action.

You can achieve the same imperatively within the method body as follows:

public ActionResult About()
        {
            if (ClaimsAuthorization.CheckAccess("Show", "Code"))
            {
                ViewBag.Message = "This is the secret code.";
            }
            else
            {
                ViewBag.Message = "Too bad.";
            }

            return View();
        }

The CheckAccess method has an overloaded version which accepts an AuthorizationContext object, which gives the highest degree of freedom to specify all the resources and actions that are needed by the auth logic.

In case you wish to protect the entire controller, then it’s possible as well:

[ClaimsAuthorize("Show", "Everything")]
    public class HomeController : Controller

If you want to apply the attribute to the entire application you can do it by adding the attribute to the global filters in App_Data/FilterConfig as follows:

public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new ClaimsAuthorizeAttribute());
        }
    }

This discussion should be enough for you to get started with Claims-based authentication and authorisation in an MVC4 internet application. In the next post we’ll start looking at separating out the login mechanism entirely: Single SignOn and Single SignOut.

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

Claims-based authentication in MVC4 with .NET4.5 C# part 2: storing authentication data in an authentication session

In the previous post we built a simple claims-aware MVC4 internet application. We saw that calling the Authenticate method in CustomClaimsTransformer.cs with every page refresh might not be desirable. In this post we’ll look at caching possibilities so that we don’t need to look up the claims of the user in the DB every time they request a page in our website.

Basics

The claims transformation pipeline will look as follows with auth sessions:

Upon the first page request:

  1. Authentication
  2. Claims transformation
  3. Cache the ClaimsPrincipal
  4. Produce the requested page

Upon subsequent page requests:

  1. Authentication
  2. Load cached ClaimsPrincipal
  3. Produce the requested page

You can immediately see the benefit: we skip the claims transformation step after the first page request so we save the potentially expensive DB lookups.

By default the authentication session is saved in a cookie. However, this is customisable and there are some advanced scenarios you can do with the auth session.

The authentication session is represented by an object called SessionSecurityToken. It is a wrapper around a ClaimsPrincipal object and can be read and written to using a SessionSecurityTokenHandler.

Demo

Open the MVC4 project we started building in the previous post. In order to introduce auth session caching we need to start with our web.config, so open that file.

We need to define some config sections for System.identityModel and system.identityModel.services. Add the following sections within the configSection element in web.config:

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

Build the application so that even IntelliSense will be aware of the new config sections when you modify web.config later on.

By default the authentication session feature will only work through SSL. This is well and good but may be an overkill for a local demo app. To disable it let’s add the following bit of XML somewhere within the configuration element in web.config:

<system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="false" />
    </federationConfiguration>
  </system.identityModel.services>

Remember to turn it on again for the production environment and install your X509 certificate.

The next step in the web.config is to register the module that will handle the auth sessions. Add the following module within the system.webServer element:

<modules>
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"></add>
    </modules>

This module will be activated at the post-authentication stage. It will attempt to acquire the auth cookie and turn it to a ClaimsPrincipal.

The last step in web.config is to register our custom claims transformation class:

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

The type value is built up as follows: [namespace.class],[assembly]. You can find the assembly name under the project properties.

We can now register the session in our code. Go to CustomClaimsTransformer.cs and update the Authenticate method as follows:

public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            if (!incomingPrincipal.Identity.IsAuthenticated)
            {
                return base.Authenticate(resourceName, incomingPrincipal);
            }

            ClaimsPrincipal transformedPrincipal = DressUpPrincipal(incomingPrincipal.Identity.Name);

            CreateSession(transformedPrincipal);

            return transformedPrincipal;
        }

…where CreateSession look as follows:

private void CreateSession(ClaimsPrincipal transformedPrincipal)
        {
            SessionSecurityToken sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));
            FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken);
        }

We create a SessionSecurityToken object and pass in the transformed principal and an expiration. By default the auth session mechanism works with absolute expiration, we’ll see later how to implement sliding expiration. Then we write that token to a cookie. From this point on we don’t need to run the transformation logic any longer.

Go to Global.asax and comment out the Application_PostAuthenticateRequest() method. We don’t want to run the auth logic upon every page request, so this is redundant code.

Instead we need to change our Login page. Go to Controllers/AccountController.cs and locate the following HTTP POST action:

public ActionResult Login(LoginModel model, string returnUrl)

In there you’ll see the following code bit:

if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
            {
                return RedirectToLocal(returnUrl);
            }

It is here we’ll call our auth session manager to set the auth cookie as follows:

if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
            {
                List<Claim> initialClaims = new List<Claim>();
                initialClaims.Add(new Claim(ClaimTypes.Name, model.UserName));
                ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(initialClaims, "Forms"));
                ClaimsAuthenticationManager authManager = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
                authManager.Authenticate(string.Empty, claimsPrincipal);
                return RedirectToLocal(returnUrl);
            }

We first create an initial set of claims. We only add in the Name claim as it is sufficient for our demo purposes but you’ll need to pass in everything that’s needed by the claims transformation logic in the custom Authenticate method. Then we create a new ClaimsPrincipal object and pass it into our transformation logic which in turn will fetch all the necessary claims about the user and set up the auth session. Note that we new up a ClaimsAuthenticationManager by a long chain of calls, but what that does is that it extracts the registered auth manager from the web.config, which is CustomClaimsTransformer.cs. We finally call the Authenticate method on the auth manager.

This code is slightly more complicated than in pure Forms based auth scenarios where a single call to FormsAuthentication.SetAuthCookie would have sufficed. However, you get a lot more flexibility with claims; you can pass in a whole range of input claims, can call your claims transformation logic and you also get a cookie that serialises the entire claim set.

Set a breakpoint at the first row of CustomClaimsTransformer.Authenticate. Run the application now. There should be no visible difference in the behaviour of the web app, but the underlying authentication plumbing has been changed. One difference in code execution is that the Authenticate method is not called with every page request.

Now log on to the site. Code execution should stop at the break point. Insect the incoming ClaimsPrincipal and you’ll see that the name claim we assigned in the Login action above is readily available:

Name claim available after auth session

Step through the code in CustomClaimsTransformer.cs and you’ll see that the SessionSecurityToken has been established and written to a cookie.

Where is that cookie?

With the web app running in IE press F12 to open the developer tools. Click the Network tab and press Start capturing:

Start capturing developer tools

Click on the About link on the web page. You’ll see that the URL list of the Developer Tool fills up with some items that the page loaded, e.g. site.css. You’ll see a button with the caption ‘Go to detailed view’ to the right of ‘Stop capturing’. This will open a new section with some new tabs. Select the ‘Cookies’ tab. You may see something like this:

Authentication session cookie

I highlighted ‘FedAuth’ which is the default name given the authentication session cookie. Its value is quite big as we’re serialising a whole claim set. Don’t worry much about the size of this long string. If the serialised value becomes too big, then the part that does not fit into FedAuth will be added to another cookie called FedAuth1 and so on. Cookies are partitioned into chunks of 2KB.

You may be wondering what the .ASPXAUTH cookie is doing there, which is the traditional auth cookie set in a forms-based authentication scenario. If you check the code in the Login action again you’ll see a call to WebSecurity.Login. It is here that the .ASPXAUTH cookie will be set. You can read more about WebSecurity in my previous blog posts on Forms auth here and here.

Logging out

This should be easy, right? Just press the Logout link and you’re done. Well, try it! You’ll see that you cannot log out; it will still say Hello, [username]. Recall that the auth session was persisted to a cookie and we specified an absolute expiration of 8 hours. Go to AccountController.cs and locate the Logoff action. You’ll see a call to WebSecurity.Logout() there which only removes the .ASPXAUTH cookie. Check the cookies collection in the Developer Tools:

web security removes aspxauth cookie

However, we still have our FedAuth cookie. So even if you log out, the FedAuth cookie will be sent along every subsequent request and from the point of view of the application you are still authenticated and logged in. Add the following code the the LogOff action in order to remove the FedAuth cookie as well:

FederatedAuthentication.SessionAuthenticationModule.SignOut();

Try again to log on and off, you should succeed.

Events

You can attach events to SessionAuthenticationModule:

  • SessionSecurityTokenReceived: modify the token as you wish, or even cancel it
  • SessionSecurityTokenCreated: modify the session details
  • SignedIn/SignedOut: raise event when the user signs in or out
  • SignOutError: raise event if there is an error when signing out

You can hook up the events in CustomClaimsTransformer.CreateSession as follows:

private void CreateSession(ClaimsPrincipal transformedPrincipal)
        {
            SessionSecurityToken sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));            
            FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken);
            FederatedAuthentication.SessionAuthenticationModule.SessionSecurityTokenCreated += SessionAuthenticationModule_SessionSecurityTokenCreated;
        }

        void SessionAuthenticationModule_SessionSecurityTokenCreated(object sender, SessionSecurityTokenCreatedEventArgs e)
        {
            throw new NotImplementedException();
        }

Sliding expiration

SessionSecurityTokenReceived event is useful if you want to set a sliding expiration to the auth session. It’s generally a bad idea to set a sliding expiration to a cookie; a cookie can be stolen and with sliding expiration in place it can be used forever if the expiry date is renewed over and over again. So normally the default setting of absolute expiration is what you should implement.

You can reissue the cookie in the SessionSecurityTokenReceived event as follows:

private void CreateSession(ClaimsPrincipal transformedPrincipal)
        {
            SessionSecurityToken sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));            
            FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken);
            FederatedAuthentication.SessionAuthenticationModule.SessionSecurityTokenReceived += SessionAuthenticationModule_SessionSecurityTokenReceived;
        }

        void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
        {
            SessionAuthenticationModule sam = sender as SessionAuthenticationModule;
            e.SessionToken = sam.CreateSessionSecurityToken(...);
            e.ReissueCookie = true;
        }

You will have access to the current session token in the incoming SessionSecurityTokenReceivedEventArgs parameter. Here you have the chance to inspect the token as you wish. Here we set the SessionToken property to a new token – I omitted the constructor parameters for brevity. You can obviously use the same session creating logic as in the CreateSession method, the CreateSessionSecurityToken is just another way to achieve the same goal.

Set a break point at…

SessionAuthenticationModule sam = sender as SessionAuthenticationModule;

…and run the application. Code execution will stop at the break point when logging in. The event will be then raised on every subsequent page request and the session security token will be reissued over and over again.

Cookie handling

It is a good idea to protect the auth session cookie so that it cannot easily be read. Fortunately the session token is by default protected by the token handler using DPAPI. The key that’s used to encrypt the token is local to the server. This means that you will run into problems in a web farm scenario where each server has a different machine key. In this case you’ll need a shared key.

You can build a new class that derives from SessionSecurityTokenHandler and set your encryption logic as you wish.

Alternatively starting with .NET4.5 there’s a built-in token handler that uses the ASP.NET machine key to protect the cookie. You can find more details on the MachineKeySessionSecurityTokenHandler class on MSDN. The shared key material will be used to protect the cookie. It won’t make any difference which server the browser connects to.

Server side caching

In case you need a large amount of claims to get the job done the auth session cookie size may grow considerably large. This may become an issue in mobile networking where the mobile device can have a slow connection. The good news is that session tokens can be cached on the server as well. It is only the session token identifier that will be sent back and forth between the browser and the server. The auth framework will find the claims collection on the server based on the identifier; you don’t need to write code to find it yourself. You can achieve this in code as follows:

SessionSecurityToken sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));
            sessionSecurityToken.IsReferenceMode = true;

The downside is that the cookie is linked to server, i.e. we have to deal with server-affinity; if the app pool is refreshed, e.g. when you deploy your web app, or reset IIS, then the claims will be lost. Also, this solution does not work out of the box in the case of web farms. A way to solve this is to introduce your own implementation of SessionSecurityTokenCache (Read on MSDN) to connect to another server dedicated to caching, such as AppFabric caching.

This post discussed the properties of the authentication session. In the next post we’ll look at claims-based authorisation in MVC4.

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

Claims-based authentication in MVC4 with .NET4.5 C# part 1: Claims transformation

This post will look into how Claims can be introduced in an MVC4 internet application.

We will build on the basics of claims we discussed in previous posts:

I will make references to those posts and if you have absolutely no experience with Claims-based auth in .NET4.5 then I suggest you take a look at them as well.

Start Visual Studio and create a new MVC4 internet application with .NET4.5 as the underlying framework.

The template will set up a good starting point for an MVC web app including forms based authentication. Run the application and click the ‘Register’ link in the top right hand corner of the screen. You’ll be redirected to a page where you can fill out the user name and password:

Register link in basic MVC4 web app

Fill in the textboxes, press the ‘Register’ button and there you are, you’ve created a user. You’ll see that you were also automatically logged on:

User automatically logged in upon registration

A short aside on forms-based auth in MVC4

The default structure of creating and authenticating users in the basic template MVC4 app is far from ideal. I wrote two posts on forms-based auth in MVC4 here and here where you can learn more on this topic and how you can transform the template to something that’s a more suitable starting point.

For now just accept that the user you created in the previous step is saved in an attached local SQL Express database that was created for you. You can view this database by looking at the Server Explorer (Ctrl W, L). There you should see a database called DefaultConnection:

Default connection database

Open that node and you’ll see several tables that .NET created for you when the first user was registered. You’ll find a detailed discussion on what they are and how they were created in the posts on forms-based auth I mentioned above. For now it’s enough to say that the user was saved in two different tables. One’s called webpages_Membership, where the password is stored in a hashed form. The table UserProfile stores the user name. Right-click that table and select ‘Show table data’ from the context menu. There you should see the user with user id = 1:

Registered user in DB

Open the membership table as well to view how the password is stored.

In case you’re wondering about what connection string was used you can see it in web.config:

<connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ClaimsInMvc4-20130130200447;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ClaimsInMvc4-20130130200447.mdf" providerName="System.Data.SqlClient"/>
 </connectionStrings>

Claims transformation in MVC4

If you recall from part 3 we registered a claims transformation logic in our simple Console application. Our goal is to do the same in our web app.

Right-click the web project in the Solution Explorer and add a new class file called CustomClaimsTransformer. The class must derive from ClaimsAuthenticationManager in the System.Security.Claims namespace. You will have add two references to your project: System.IdentityModel and System.IdentityModel.Services. The skeleton of the class will look like this:

public class CustomClaimsTransformer : ClaimsAuthenticationManager
    {
    }

We will override the Authenticate method:

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

This structure should look familiar from Part 3 of Claims basics. The resource name is an optional variable to describe the resource the user is trying to access. The incoming ClaimsPrincipal object is the outcome of the authentication; it represents the User that has just been authenticated on the login page. Now we want to ‘dress up’ the claims collection of that user.

Our first check is to see if the ClaimsPrincipal has been authenticated.

public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            if (!incomingPrincipal.Identity.IsAuthenticated)
            {
                return base.Authenticate(resourceName, incomingPrincipal);
            }
        }

If the user is anonymous then we let the base class handle the call. The Authenticate method in the base class will simply return the incoming principal so an unauthenticated user will not gain access to any further claims and will stay anonymous.

You will typically not have access to a lot of claims right after authentication. You can count with the bare minimum of the UserName and often that’s all you get in a forms-based login scenario. So we will simulate a database lookup based on the user name. The user’s claims are probably stored somewhere in some storage. We’ll start with a skeleton:

public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
            if (!incomingPrincipal.Identity.IsAuthenticated)
            {
                return base.Authenticate(resourceName, incomingPrincipal);
            }

            return DressUpPrincipal(incomingPrincipal.Identity.Name);
        }

        private ClaimsPrincipal DressUpPrincipal(String userName)
        {

        }

However, in case the application is expecting more Claims than the name claim at this stage then this is the time to check the claims collection. If you need access to an “age” claim then you can check its presence through the Claims property of the ClaimsPrincipal:

incomingPrincipal.Claims.Where(c => c.Type == "age").FirstOrDefault();

Then if the age claim is missing then you can throw an exception.

Fill in the DressUpPrincipal method as follows:

private ClaimsPrincipal DressUpPrincipal(String userName)
        {
            List<Claim> claims = new List<Claim>();

            //simulate database lookup
            if (userName.IndexOf("andras", StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                claims.Add(new Claim(ClaimTypes.Country, "Sweden"));
                claims.Add(new Claim(ClaimTypes.GivenName, "Andras"));
                claims.Add(new Claim(ClaimTypes.Name, "Andras"));
                claims.Add(new Claim(ClaimTypes.Role, "IT"));
            }
            else
            {
                claims.Add(new Claim(ClaimTypes.GivenName, userName));
                claims.Add(new Claim(ClaimTypes.Name, userName));
            }

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

So we add some claims based on the user name. Here you would obviously do some check in your data storage. If you have Roles in your web app, which is probably true for 99% of all .NET web apps with .NET4 and lower, then you can still use them by the ‘Role’ property of ClaimTypes. You can run the good old Roles.GetRolesForUser(string userName) method of ASP.NET Membership and assign the resulting string array to the Claims.

Finally we return a new ClaimsPrincipal which includes the result of our datastore lookup. Keep in mind that you need to specify the authentication type with a string to make the ClaimsPrincipal authenticated. Here we assigned “Custom” to that value, but it’s up to you.

Now we need to invoke our custom auth logic. We will do that at application start-up in Global.asax. The method that we want to implement is called PostAuthenticationRequest.

First we need to get hold of the current principal, i.e. the one that has just logged in:

protected void Application_PostAuthenticateRequest()
        {
            ClaimsPrincipal currentPrincipal = ClaimsPrincipal.Current;
        }

We will then reference our custom auth manager, pass in the current principal, retrieve the transformed principal and set the transformed principal to the current thread and current user:

protected void Application_PostAuthenticateRequest()
        {
            ClaimsPrincipal currentPrincipal = ClaimsPrincipal.Current;
            CustomClaimsTransformer customClaimsTransformer = new CustomClaimsTransformer();
            ClaimsPrincipal tranformedClaimsPrincipal = customClaimsTransformer.Authenticate(string.Empty, currentPrincipal);
            Thread.CurrentPrincipal = tranformedClaimsPrincipal;
            HttpContext.Current.User = tranformedClaimsPrincipal;
        }

Set a breakpoint at the first row within Application_PostAuthenticateRequest and run the application. Code execution should stop at the breakpoint. Step through the code using F11. As the user is anonymous base.Authenticate will be invoked within CustomClaimsTransformer.Authenticate. The anonymous user will be set as the current principal of the thread with no claims attached.

Remove the breakpoint from within the Application_PostAuthenticateRequest(), we don’t need that. Instead set a new breakpoint within CustomClaimsTransformer.Authenticate where you call the DressUpPrincipal method. We only want to stop code execution if something interesting happens.

Now use the user created before to log in. Code execution should stop within the Authenticate method as the user is not anonymous any more. Use F11 to step through the code line by line. You should see that the user receives the assigned claims and is set as the current user of the current thread and HttpContext.

Let the rest of the code run and… …you may be greeted with a mystical InvalidOperationException:

A claim of type ‘http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier&#8217; or ‘http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider&#8217; was not present on the provided ClaimsIdentity. To enable anti-forgery token support with claims-based authentication, please verify that the configured claims provider is providing both of these claims on the ClaimsIdentity instances it generates. If the configured claims provider instead uses a different claim type as a unique identifier, it can be configured by setting the static property AntiForgeryConfig.UniqueClaimTypeIdentifier.

It turns out the AntiForgeryToken is expecting BOTH the NameIdentifier and IdentityProvider claim even if the exception message says OR. If you recall our implementation of DressUpPrincipal then we omitted both. So let’s go back and include the NameIdentifier:

//simulate database lookup
            if (userName.IndexOf("andras", StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                claims.Add(new Claim(ClaimTypes.Country, "Sweden"));
                claims.Add(new Claim(ClaimTypes.GivenName, "Andras"));
                claims.Add(new Claim(ClaimTypes.Name, "Andras"));
                claims.Add(new Claim(ClaimTypes.NameIdentifier, "Andras"));
                claims.Add(new Claim(ClaimTypes.Role, "IT"));
            }
            else
            {
                claims.Add(new Claim(ClaimTypes.GivenName, userName));
                claims.Add(new Claim(ClaimTypes.Name, userName));
                claims.Add(new Claim(ClaimTypes.NameIdentifier, userName));
            }

Note the ClaimTypes.NameIdentifier in the claims collection. If you run the application now you should still get the same exception which proves the point that by default BOTH claims are needed for the AntiForgeryToken. You can avoid adding both claims by adding the following bit of code in Application_Start within Global.asax:

AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;

Re-run the application and you should be able to log in without getting the exception.

You’ll notice that the text where it says ‘Register’ changes to Hello, [username] upon successful login. Where is that value coming from? Navigate to Views/Shared/_Layout.cshtml in the Solution Explorer and locate the following element:

<section id="login">

This element includes a reference to a partial view “_LoginPartial”. You’ll find _LayoutPartial.cshtml in the same folder. At the top of that file you’ll see the following code:

@if (Request.IsAuthenticated) {
    <text>
        Hello, @Html.ActionLink(User.Identity.Name, "Manage", "Account", routeValues: null, htmlAttributes: new { @class = "username", title = "Manage" })!
        @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
            @Html.AntiForgeryToken()
            <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
        }
    </text>
}

Note the call to User.Identity.Name after ‘Hello’. This is a conservative approach as the MVC4 template has no way of knowing in advance whether you’re planning to make you application claims-aware. User is an IPrincipal and Identity is an IIDentity so it will work with pre-.NET4.5 claims auth identity types as well. However, we know that we use claims, so let’s replace User.Identity.Name with:

System.Security.Claims.ClaimsPrincipal.Current.FindFirst(System.IdentityModel.Claims.ClaimTypes.GivenName).Value

Run the web app, log in and you should see the GivenName claim instead of the generic IPrincipal.Name.

Since the web app is now claims-aware you can use the claims to show the email claim after login or the user’s favourite colour or what have you, as long as that particular Claim is present. This was not so easily available with the good old GenericPrincipal and WindowsPrincipal objects.

Note an important thing: do you recall that we hooked up our custom auth manager in Global.asax by overriding Application_PostAuthenticateRequest()? In fact what happens is that our custom Authenticate method in CustomClaimsTransformer.cs runs with every single page request. Set a breakpoint within the method and code execution will stop every time you navigate to a page in the web app. The real implementation of the Authenticate method will most likely involve some expensive DB lookup which then also runs with every page request. That’s of course not maintainable.

How can we solve that problem? By caching the outcome of the Authenticate method in a built-in authentication session.
That’s what we’ll look at in the next blog post.

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

Introduction to Claims based security in .NET4.5 with C# Part 4: authorisation with claims

At the end of the previous blog post on Claims transformation we ended up with a basic console application where we transformed the incoming Claims collection according to our own needs. We will now make use of those claims to control access to parts of our code.

Overview

The traditional way of authorising access certain parts of our application in .NET was usually performed through the .IsInRole method if you took the .NET Membership framework. You may have ended up with a bunch of if-else cases: if the user is in the Marketing group, then do this, else if the user is a Customer, then do something else. This is not optimal as we’re mixing our business logic with authorisation and is hard to maintain. Also, the number of groups could grow a lot over time. Maybe you didn’t want to allow access to a certain action for everyone in Marketing. Then you’d have to add specialised groups likes MarketingManager, MarketingAdmin, MarketingSimple etc. Also, if a certain action could be carried out by Marketing, Sales and Admins, then you’d have to remember to check if the user is in any of these roles. Claims allow more fine-grained control over authorisation. You are not constrained to Roles and Groups any more. Example: if you have a method called InsertUser then you can set the access to that method by decorating it with the following attribute:

[ClaimsPrincipalPermission(SecurityAction.Demand, Operation="Insert", Resource="User")]

This looks a lot like how we used to write before .NET4.5 with the PrincipalPermission attribute. The fundamental difference is that with PrincipalPermission we checked if the user was in a certain role as follows:

[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]

…which means that you are allowed to carry out this method only if you are in the Administrator role. The new way of setting permissions is that we state that we have an Operation called “Insert” paired with a Resource called “User”. It is not specified WHO is allowed to carry out the action because that type of check does not fit in our business logic. A method called InsertUser will most likely involve inserting a user as described by the attributes and this is unlikely to change over time. However, rules over WHO is allowed to carry out an action will almost certainly change. The new ClaimsPrincipalPermission attribute doesn’t care about which role a user is in. It only states what the method is doing: ‘This method INSERTs a new USER’.

We can write our own AuthorizationManager by deriving from the ClaimsAuthorizationManager superclass. The ClaimsPrincipalPermission attribute will invoke our custom authorisation class where we can check if the user is allowed to carry out the Operation defined by the attribute on the Resource defined by the attribute. Maybe the user is allowed to INSERT certain objects, but not new Users, maybe only new Products.

It is good idea to separate out the authorisation logic as much as possible, possibly even hiding it behind an API in a different assembly so that it can be updated and deployed independently from your main application.

Authorisation demo

Open the solution we built in the previous post. Add the following skeleton to Main:

private static void ShowMeTheCode()
        {

        }

Before claims and .NET4.5 you may have introduced if-else clauses within the method to decide who can do what: if the user is so and so, then follow this path, else follow another path. This leads to an ugly mix of business and auth logic. Instead we’ll follow the way we looked at in the introduction:

        [ClaimsPrincipalPermission(SecurityAction.Demand, Operation="Show", Resource="Code")]
        private static void ShowMeTheCode()
        {
            Console.WriteLine("Console.WriteLine");
        }

Before the ShowMeTheCode is run we demand that the user has access to the Operation ‘Show’ and the Resource ‘Code’. The method simply displays a short string and the attribute is telling us that the current user must make sure he has the right claims.

How can we evaluate that? Add a new class to the project called CustomAuthorisationManager. The class will derive from ClaimsAuthorizationManager in the System.Security.Claims namespace:

public class CustomAuthorisationManager : ClaimsAuthorizationManager
    {
    }

We must override the CheckAccess method:

        public override bool CheckAccess(AuthorizationContext context)
        {
            return base.CheckAccess(context);
        }

Set a breakpoint at the call to base.CheckAccess. Also, extend UseCurrentPrincipal to call the ShowMeTheCode() method:

        private static void UseCurrentPrincipal()
        {
            ShowMeTheCode();
        }

Set another breakpoint within the UseCurrentPrincipal method and run the application. The execution will stop at the call to ShowMeTheCode() within UseCurrentPrincipal. Use F11 to continue and you’ll see that nothing special happens, the ShowMeTheCode method executes and the program finishes. So what happened to our custom authorisation code? Just like in the case of the CustomClaimsTransformer class the CustomAuthorisationManager class also needs to be registered in web.config. Extend the system.identityModel node as follows:

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

You’ll see an element called claimsAuthorizationManager where you must specified the fully qualified name of the custom auth class and the assembly. So let’s try running the application again. This time the execution should stop at base.CheckAccess within the CheckAccess method. Before you let the code execution continue inspect the incoming AuthorizationContext object. Click on ‘AuthorizationContext’ and press F12 to see what’s available in that class.

This object will include information about the user who’s trying to access the method. The ‘Principal’ property will describe the current User. You also have access to the Resource(s) and the Action(s) that the user is trying to run. Note that these last two are both claim collections.

Now inspect the incoming AuthorizationContext object in the Locals window. You can check the Resource and Action values as follows:

Authorization context

These values were passed in via the ClaimsPrincipalPermission attribute and are converted into claims, i.e. not simple string values. These claims are added into a Claims collection which allows us to extend the claims that are necessary to run a specific method. Maybe it’s not enough to have access to one resource, but 3 and that user must be allowed to insert AND update these resources. This gives us an opportunity to build more elaborate access rules. In that case the simple Resource and Actions strings in the ClaimsPrincipalPermission attribute will not suffice. We’ll need to construct our AuthorizationContext object and manually call our auth logic. We’ll take a look at how that works further down.

You can also see the two claims we specified for the user in the previous post:

Authorization context principal

Let’s change the CheckAccess method to the following:

        public override bool CheckAccess(AuthorizationContext context)
        {
            string resource = context.Resource.First().Value;
            string action = context.Action.First().Value;

            if (action == "Show" &amp;&amp; resource == "Code")
            {
                bool likesJava = context.Principal.HasClaim("http://www.mysite.com/likesjavatoo", "True");
                return likesJava;
            }

            return false;
        }

First we extract the resource and action values. The HasClaim method will check if the current principal has the right claim type and that it has a value of ‘true’. So if the current user likes Java then we’ll allow them to run the ShowMeTheCode method. In all other cases we’ll return false, i.e. no-one else should have access to that method.

Set a breakpoint at ‘string resource = context.Resource.First().Value;’ and run the application. Step through the CheckAccess method line by line. You’ll see that the current user has been given access and is allowed to carry out the protected code. Simulate a change in the auth logic by having the exact opposite return value:

return !likesJava;

Run the application and you should get a SecurityException with the following message:

ID4266: Request for ClaimsPrincipalPermission failed for: Action: ‘System.Collections.ObjectModel.Collection`1[System.Security.Claims.Claim]’, Resource: ‘System.Collections.ObjectModel.Collection`1[System.Security.Claims.Claim]’.

Obviously you’d need to catch this type of exception when you call this method. The point, however, is that now people who like Java are not allowed to run the protected method.

Remove the ‘!’ from the return statement to go back to the previous state.

In case you don’t like attributes then the auth manager can be called imperatively as follows:

ClaimsPrincipalPermission.CheckAccess("Code", "Show");

In case of complicated auth rules

As mentioned above it’s possible to have a collection of Resources and Actions. In that case the simple ClaimsPrincipalPermission will not be enough. We have to first reference our auth logic manually and invoke the CheckAccess method on that. You can then define your own Claims collections in the AuthorizationContext object:

ClaimsAuthorizationManager authManager = 
                FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager;

            Collection<Claim> resourceClaims = new Collection<Claim>();
            resourceClaims.Add(new Claim("resource1", "value1"));
            resourceClaims.Add(new Claim("resource2", "value2"));

            Collection<Claim> actionClaims = new Collection<Claim>();
            actionClaims.Add(new Claim("action1", "insert"));
            actionClaims.Add(new Claim("action2", "update"));

            AuthorizationContext authContext = new AuthorizationContext(ClaimsPrincipal.Current, resourceClaims, actionClaims);
            bool allowed = authManager.CheckAccess(authContext);

The authManager.CheckAccess call will go to our custom auth logic. You can use the returned bool value to tweak your code. This provides the ultimate flexibility to control authorisation in case of a complex auth logic with multiple resources and actions.

This completes the discussion about Claims basics. In the next post we’ll start looking at Claims in an MVC4 internet application.

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

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.

Introduction to Claims based security in .NET4.5 with C# Part 2: the new inheritance model

The previous blog post introduced how Claims are handled in .NET4.5. This blog will will discuss the new inheritance model of the IPrincipal and IIdentity interfaces.

The new inheritance model

Before .NET4.5 the built-in GenericPrincipal and WindowsPrincipal objects directly implemented the IPrincipal interface. GenericIdentity and WindowsIdentity inturn implemented the IIdentity interface. With .NET4.5 we can see a new philosophy: Claims must be readily available in any new .NET projects that have .NET4.5 as the underlying framework. The new inheritance structure is as follows:

  • ClaimsPrincipal implements IPrincipal
  • GenericPrincipal and WindowsPrincipal directly derive from ClaimsPrincipal
  • Therefore GenericPrincipal and WindowsPrincipal do not directly implement IPrincipal any more

Conclusion: even if you have never even heard of Claims and continue to use the ‘old’ GenericPrincipal and WindowsPrincipal objects you indirectly use ClaimsPrincipal even if it is not obvious at first. If you upgrade your .NET4 project to .NET4.5 then your authentication logic will not break and you will have access to the new features of ClaimsPrincipal through GenericPrincipal and WindowsPrincipal as well.

We see the same changes with IIdentity. Before .NET4.5 we had built-in implementations of IIdentity such as GenericIdentity, WindowsIdentity. Now we have one object, the ClaimsIdentity that directly implements IIdentity and the other two derive directly from ClaimsIdentity.

In other words: ClaimsPrincipal and ClaimsIdentity provide a common ground, a common base class for the objects that directly derive from it. If you have an intranet application with Windows Auth then all the specific properties available in WindowsIdentity and WindowsPrincipal, such as Impersonation or User token will be stored in the ClaimsCollection.

This also means that if you plan to build your own Identity and Principal objects then you should not implement IIdentity and IPrincipal but derive from ClaimsPrincipal and ClaimsIdentity instead. You will then have access to all the new features of Claims as well.

Claims inheritance demo

Fire up Visual Studio 2012 and create a new Console application with .NET4.5 as the underlying framework.

In the Main method add the following code to create a new WindowsIdentity:

WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent();

Set a breakpoint at this bit of code and run the application. Inspect ‘windowsIdentity’ in the Locals window and check its base class:

Windows Identity derives from Claims Identity

It’s easy to see that WindowsIdentity indeed derives from ClaimsIdentity. Scroll down the Locals window and you’ll see that WindowsIdentity has access to the Claims collection of its superclass:

Windows claims collection

The Claims collection has been populated mostly with the well-known WindowsIdentity Group SIDs.

Let’s have a look at GenericIdentity. Add the following code to Main:

GenericIdentity genericIdentity = new GenericIdentity("Andras");

Inspect the ‘genericIdentity’ variable in the Locals window and you’ll see again that the Claims collection has been populated with the Name claim:

GenericIdentity claims collection

This is great. Even if you use the old-style WindowsIdentity and GenericIdentity objects you have access to the Claims collection that you can query.

Build your own IIdentity object

In the past if you needed to build your own IIdentity object then you may have done something like this:

public class CompanyIdentity : IIdentity
    {
        public CompanyIdentity(string location, int allowance)
        {
            Location = location;
            Allowance = allowance;
        }

        public String Location { get; set; }
        public int Allowance { get; set; }


        public string AuthenticationType
        {
            get { throw new NotImplementedException(); }
        }

        public bool IsAuthenticated
        {
            get { throw new NotImplementedException(); }
        }

        public string Name
        {
            get { throw new NotImplementedException(); }
        }
    }

You may have implemented the IIdentity interface and added the custom properties that represent a User. These extra properties, such as Location are nothing but Claims really.

Today you would instead inherit from the ClaimsPrincipal object and populate the Claims collection with the AddClaim method:

public class CompanyIdentity : ClaimsIdentity
    {
        public CompanyIdentity(string location, int allowance)
        {
            AddClaim(new Claim(ClaimTypes.Locality, location));
            AddClaim(new Claim("http://www.mycompany.com/allowance", allowance.ToString()));
        }

        public string Location
        {
            get
            {
                return FindFirst(ClaimTypes.Locality).Value;
            }
        }

        public int Allowance
        {
            get
            {
                return Convert.ToInt32(FindFirst("http://www.mycompany.com/allowance").Value);
            }
        }
    }

The Location and Allowance getters are optional. You can directly inspect the claims collection of the CompanyIdentity object. The getters are there for convenience.

This was a rather short post dedicated to the new Identity and Principal inheritance model in .NET4.5. The next post will deal with claims transformation, i.e. how you can “dress up” an initial set of claims with new ones before your auth logic kicks in.

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

Introduction to Claims based security in .NET4.5 with C# Part 1: the absolute basics

The well-known built-in Identity objects, such as GenericPrincipal and WindowsPrincipal have been available for more than 10 years now in .NET. Claims were introduced in .NET4.5 to build Claims based authentication into the framework in the form of ClaimsIdentity and ClaimsPrincipal in the System.Security.Claims namespace.

Before we see some action in terms of code let’s look at a general description of claims. If you already know what they are and want to see the code then you can safely jump this section.

What is a claim?

A claim in the world of authentication and authorisation can be defined as a statement about an entity, typically a user. A claim can be very fine grained:

  • Tom is an administrator
  • Tom’s email address is tom@yahoo.com
  • Tom lives in Los Angeles
  • Tom’s allowed to view sales figures between 2009 and 2012
  • Tom’s allowed to wipe out the universe

If you are familiar with Roles in the ASP.NET Membership framework then you’ll see that Roles are also claim types. Claims come in key-value pairs:

  • Role: administrator
  • Email: tom@yahoo.com
  • Address: Los Angeles
  • Viewable sales period: 2009-2012

These statements are a lot more expressive than just putting a user in a specific role, such as marketing, sales, IT etc. If you want to create a more fine-grained authorisation process then you’ll need to create specialised roles, like the inevitable SuperAdmin and the just as inevitable SuperSuperAdmin.

Claims originate from a trusted entity other than the one that is being described. This means that it is not enough that Tom says that he is an administrator. If your company’s intranet runs on Windows then Tom will most likely figure in Active Directory/Email server/Sales authorisation system and it will be these systems that will hold these claims about Tom. The idea is that if a trusted entity such as AD tells us things about Tom then we believe them a lot more than if Tom himself comes with the same claims. This external trusted entity is called an Issuer. The KEY in the key-value pairs is called a Type and the VALUE in the key-value pair is called the Value. Example:

  • Type: role
  • Value: marketing
  • Issuer: Active Directory

Trust is very important: normally we trust AD and our own Exchange Server, but it might not be as straightforward with other external systems. In such cases there must be something else, e.g. a certificate that authenticates the issuer.

An advantage of claims is that they can be handled by disparate authentication systems which can have different implementations of claims: groups, roles, permissions, capabilities etc. If two such systems need to communicate through authorisation data then Claims will be a good common ground to start with.

How do we attach these claims to the Principals?

A Claim is represented in .NET4.5 by an object called… …Claim! It is found in the System.Security.Claims namespace.

There is a new implementation of the well-known IIdentity interface called ClaimsIdentity. This implementation holds an IEnumerable of Claim objects. This means that this type of identity is described by an arbitrary number of statements.

Not surprisingly we also have a new implementation of IPrincipal called ClaimsPrincipal which holds a read-only collection of ClaimsIdentity objects. Normally this collection of identities will only hold one ClaimsIdentity element. In some special scenarios with disparate systems a user can have different types of identities if they can identify themselves in multiple ways. The ClaimsPrincipal implementation accommodates this eventuality.

The advantage with having these new objects deriving from IPrincipal and IIdentity is compatibility. You can start introducing Claims in your project where you work with IPrincipals and IIdentities without breaking your code.

It’s been enough talk, let’s see some action

Start Visual Studio 2012 and create a new Console application with .NET4.5 as the underlying framework.

The simplest way to create a new Claim is by providing a Type and a Value in the Claim constructor:

static void Main(string[] args)
        {
            Claim claim = new Claim("Name", "Andras");
        }

You can use strings to describe types as above but we all know the disadvantages with such hard-coded strings. There is an enumeration called ClaimTypes that stores the most common claim types.

static void Main(string[] args)
        {
            Claim claim = new Claim("Name", "Andras");
            Claim newClaim = new Claim(ClaimTypes.Country, "Sweden");
        }

You can check out the values available in ClaimTypes using IntelliSense. It is safer to use the enumeration where-ever possible rather than the straight string values as chances are the system you’re trying to communicate Claims with will also understand the values behind the enumerated one. If you don’t find any suitable one there you can revert back to string-based Types and even define a formal namespace to the claim as follows:

new Claim("http://www.mycompany.com/building/floor", "Two")

Place the cursor on “Country” in ‘new Claim(ClaimTypes.Country, “Sweden”);’ and press F12. You’ll see a long list of namespaces, such as the following:

public const string Country = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";

These namespaces will uniquely describe the claim type.

It is very rare that there’s only one claim about a person. Instead, claims come in collections, so let’s create one:

static void Main(string[] args)
        {
            IList<Claim> claimCollection = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "Andras")
                , new Claim(ClaimTypes.Country, "Sweden")
                , new Claim(ClaimTypes.Gender, "M")
                , new Claim(ClaimTypes.Surname, "Nemes")
                , new Claim(ClaimTypes.Email, "hello@me.com")
                , new Claim(ClaimTypes.Role, "IT")
            };
        }

We can easily build an object of type IIDentity out of a collection of claims, in this case a ClaimsIdentity as mentioned above:

ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection);

We now test if this identity is authenticated or not:

Console.WriteLine(claimsIdentity.IsAuthenticated);

Run the Console app and test for yourself; IsAuthenticated will return false. Claims can be attached to anonymous users which is different from the standard principal types in .NET4 and earlier. It used to be enough for the user to have a name for them to be authenticated. With Claims that is not enough. Why would you attach claims to an unauthenticated user? It is possible that you gather information about a user on your site which will be used to save their preferences when they are turned into members of your site.

If you want to turn this IIdentity into an authenticated one you need to provide the authentication type which is a string descriptor:

ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, "My e-commerce website");

Run the application again and you’ll see that the user is now authenticated.

Using our identity object we can also create an IPrincipal:

ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);

As ClaimsPrincipal implements IPrincipal we can assign the ClaimsPrincipal to the current Thread as the current principal:

Thread.CurrentPrincipal = principal;

From this point on the principal is available on the current thread in the rest of the application.

Create a new method called Setup() and copy over all our code as follows:

static void Main(string[] args)
        {
            Setup();

            Console.ReadLine();
        }

        private static void Setup()
        {
            IList<Claim> claimCollection = new List<Claim>
            {
                new Claim(ClaimTypes.Name, "Andras")
                , new Claim(ClaimTypes.Country, "Sweden")
                , new Claim(ClaimTypes.Gender, "M")
                , new Claim(ClaimTypes.Surname, "Nemes")
                , new Claim(ClaimTypes.Email, "hello@me.com")
                , new Claim(ClaimTypes.Role, "IT")
            };

            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, "My e-commerce website");

            Console.WriteLine(claimsIdentity.IsAuthenticated);

            ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);
            Thread.CurrentPrincipal = principal;
        }

Let’s see if the new Claims-related objects can be used in .NET4 where Claims are not available. Create a new method as follows:

private static void CheckCompatibility()
        {

        }

Call this method from Main as follows:

static void Main(string[] args)
        {
            Setup();
            CheckCompatibility();

            Console.ReadLine();
        }

Add the following to the CheckCompatibility method:

IPrincipal currentPrincipal = Thread.CurrentPrincipal;
Console.WriteLine(currentPrincipal.Identity.Name);

Run the application and the name you entered in the claims collection will be shown on the output window. The call for the Name property will look through the claims in the ClaimsIdentity object and extracts the value of Name claim type.

In some cases it is not straightforward what a ‘Name’ type means. Is it the unique identifier of the user? Is it the email address? Or is it the display name? You can easily specify how a claim type is defined. You can pass two extra values to the ClaimsIdentity constructor: which claim type constitutes the ‘Name’ and the ‘Role’ claim types. So if you want the email address to be the ‘Name’ claim type you would do as follows:

ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, "My e-commerce website", ClaimTypes.Email, ClaimTypes.Role);

Run the application and you will see that the email is returned as the name from the claim collection.

You can check if a user is in a specific role as before:

private static void CheckCompatibility()
        {
            IPrincipal currentPrincipal = Thread.CurrentPrincipal;
            Console.WriteLine(currentPrincipal.Identity.Name);
            Console.WriteLine(currentPrincipal.IsInRole("IT"));
        }

…which will yield true.

So we now know that ‘old’ authentication code will still be able to handle the Claims implementation. We’ll now turn to ‘new’ code. Create a new method called CheckNewClaimsUsage() and call it from Main just after CheckCompatibility().
The following will retrieve the current claims principal from the current thread:

private static void CheckNewClaimsUsage()
        {
            ClaimsPrincipal currentClaimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
        }

Now you’ll have access to all the extra methods and properties built into ClaimsPrincipal. You can enumerate through the claims collection in the principal object, find a specific claim using Linq etc. Example:

private static void CheckNewClaimsUsage()
        {
            ClaimsPrincipal currentClaimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;
            Claim nameClaim = currentClaimsPrincipal.FindFirst(ClaimTypes.Name);
            Console.WriteLine(nameClaim.Value);
        }

You can use .HasClaim to check if the claims collection includes a specific claim you’re looking for.

You can also query the identities of the ClaimsPrincipal:

foreach (ClaimsIdentity ci in currentClaimsPrincipal.Identities)
            {
                Console.WriteLine(ci.Name);
            }

The line…

ClaimsPrincipal currentClaimsPrincipal = Thread.CurrentPrincipal as ClaimsPrincipal;

…becomes so common that there’s a built-in way to achieve the same thing:

ClaimsPrincipal currentClaimsPrincipal = ClaimsPrincipal.Current;

This will throw an exception if the concrete IPrincipal type is not ClaimsPrincipal for whatever reason.

We have looked at the very basics of Claims in .NET4.5. The next post will look at the new IIdentity and IPrincipal inheritance model.

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

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

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

%d bloggers like this: