2016-02-04

Introduction

In the previous post we started adding the necessary OWIN-related libraries to our Web API project: a couple of NuGet libraries and the Startup class. We publish our application to the local IIS and it doesn’t allow us to break the code within Startup.cs. We’ll soon see that we can still debug the OWIN components further down the call stack.

In this post we’ll add the necessary elements to a client certificate based authentication in .NET MVC with OWIN.

Preparations

Open the demo Web API project in Visual Studio as an administrator. Install the Microsoft.Owin.Security DLL from NuGet to the web project:



This package includes the security related classes in OWIN without which we cannot build the custom authentication mechanism.

Let’s remove all the security related demo code from CustomersController to as the next step. Normally your controllers should have no security related logic. Here’s the revised controller:

Note, however, that we’ve decorated the Get method with the familiar Authorize attribute. We only want people with a valid client certificate to be able to view the customers list.

Then insert a folder called Authentication to the Web API project. We’ll put all our authentication related classes there.

AuthenticationOptions

The OWIN namespace has a number of security related classes that we’ll see in this post. The first one is called AuthenticationOptions. It is a base class for all types of authentication options, such as CookieAuthenticationOptions, GoogleAuthenticationOptions or OpenIdConnectAuthenticationOptions. If you’d like to build your own OWIN authentication then this is the starting point.

The minimum requirement here is to derive from the AuthenticationOptions which has no virtual methods. You only need to have a constructor which accepts a string parameter which describes the authentication type. However, you are free to insert any properties and constructors as you wish. Here we’ll keep it at a minimum.

Add a class called ClientCertificateAuthenticationOptionsinto the Authentication folder:

We simply declare our authentication type in line with X509 certificates.

The authentication handler

The next class that we need to derive from is AuthenticationHandler. It is the base class for the work carried out by OWIN authentication middleware. We’ll see shortly that the implemented authentication middleware must return an authentication handler that derives from AuthenticationHandler.

AuthenticationHandler is a generic class with a type parameter. The type parameter must derive from AuthenticationOptions we discussed above. The minimum requirement is to implement the authentication logic in the AuthenticateCoreAsync method. It returns a Task of AuthenticationTicket object, i.e. it is implicitly assumed that the authentication logic will be called asynchronously in some resource intensive operation such as a database lookup.

An AuthenticationTicket, as its name implies “contains user identity information as well as additional authentication state” according to the MSDN documentation. The constructor of this object requires a claims identity – represented by the ClaimsIdentity object – and the authentication properties, which are contained by the AuthenticationProperties object.

Claims-based authentication is a large topic and there are multiple posts dedicated to it on this blog. If you don’t know what claims are then you can start here. You can also check out the Security and Cryptography index page referred to at the end of this post to find claims-related posts. Basically a claim in the world of authentication and authorisation can be defined as a statement about an entity, typically a user.

Add a class called ClientCertificateAuthenticationHandler into the Authentication folder:

…where we have a couple of new elements. The client certificate validation logic is abstracted away to an interface for loose coupling:

The ClientCertificateValidationResult is a simple object to store whether the certificate is valid or not and a list of validation exceptions:

Let’s go through the ClientCertificateAuthenticationHandler class a little bit. It derives from AuthenticationHandler of T where T is ClientCertificateAuthenticationOptions, this is in line with what we wrote in the short introduction of this section. The class has a loose dependency on IClientCertificateValidator which will perform the actual client certificate validation. We also store a key called _owinClientCertKey with the value “ssl.ClientCertificate”. If you are new to OWIN then you probably won’t understand what this is all about.

You can read about the very basics of OWIN and Katana in an introductory series starting here. Basically, in the OWIN middleware chain there’s an object called the “environment”. It is a dictionary with a key of type string and a value of type object. It contains all sorts of entries about the incoming web request. In addition, each middleware in the OWIN chain can add their own objects with a certain key. Some elements have shortcuts available through the built-in Request property, e.g. the headers or the query string. You’ll see a call for “Request.” in the following bit:

If you type “Request.” then you’ll see some shortcuts, like Request.Headers which are really only wrappers around the more direct key-based technique that we have to use for the client certificate.

So, the client certificate sent by the client is not available from some request property, you’ll need to look for it with a key, and that key is “ssl.ClientCertificate”. That’s what you’ll see in the ValidateCertificate method:

Every value in the environment dictionary is an object so it needs to be cast to its “proper” type, in this case an X509Certificate2 object. If there’s a client certificate in the web request then it is sent for validation to the certificate validator. Otherwise we return a message saying that there was no client certificate.

As you can see we retrieve the client certificate from the web request differently from how we extracted it within an MVC – or Web API – controller.

If the user is authorised, i.e. the certificate has passed the validation phase, then we build the AuthenticationTicket object. The code shows an example of building an AuthenticationProperties object. Those are of course not meaningful in our demo specifically. We also build a list of claims and you’ll see that a claim consists of a key and a value as noted above. The ClaimTypes class contains a list of well-known claim types such as Name, Email, Role etc. Those are all strings, therefore you can specify your own claim category as you wish, such as “www.mycompany.com/claims/favourite-colour”.

We return null in case authentication fails.

How do we link up all these elements with OWIN? We’ll find it out in the next post which also finishes this series.

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

Show more