Monthly Archives: September 2015

Generating and consuming JSON Web Tokens with .NET

Maybe you have read my previous blog post in which I talked about token generation in OWIN. After the issues we had there with Machine key and OWIN versions, I decided to take a look at some alternatives.

After some research I decided JSON Web Tokens (or JWT’s, which apparently should be pronounced as the English word ‘jot’) would fit the bill. They are small, it is an open standard, and has a simple string representation (URL-safe). More info on the standard can be found in this draft.

After this research it should be a easy to incorporate this into my solution right? Well… not as easy as I thought. It turns out many samples are just using an external STS to create and verify tokens, or using some own custom implementation which doesn’t support all of the options. Let alone complete samples of generating a token in a WCF service and using it in a client to pass on to another service. However after a lot of searching, researching etc. I decided to make my own sample.

So here comes the first part, generating and consuming:

I will be using the “JSON Web Token Handler for the Microsoft .NET Framework 4.5” NuGet Package as it is called by its full name. It is also called System.IdentityModel.Tokens.Jwt. So in this post I’ll just show you how to create a token from some claims and then how to turn the token back into claims again. Just in a console application so we can more easily see what is going on.

I have just created a new Console application in Visual Studio 2015, and added the aforementioned NuGet package. At the time of writing the latest stable version is 4.0.2.206221351. Don’t forget to add a reference to the System.IdentityModel assembly as well, it is part of the .NET Framework since v4.5.

First we will add some using clauses we will need:

using System.IdentityModel.Tokens;
using System.Security.Claims;

Before we can sign a token we need a secret to sign it with. There a multiple options like certificates and whatnot. The easiest to use in this example however is just a normal shared secret text. Which we will need to turn into a byte array before we can make it a secret key. Also we will have to put it in a SigningCredentials object together with the algorithms we will use to sign it with:

var plainTextSecurityKey = "This is my shared, not so secret, secret!";
var signingKey = new InMemorySymmetricSecurityKey(
    Encoding.UTF8.GetBytes(plainTextSecurityKey));
var signingCredentials = new SigningCredentials(signingKey, 
    SecurityAlgorithms.HmacSha256Signature, SecurityAlgorithms.Sha256Digest);

You can use a couple of different security algorithms but you should specify one which ends in signature for the first one, and one that ends in digest for the second algorithm. Some will throw a NotSupportedException (because, not supported) and HmacSha256Signature and Sha256Digest seem to be the default in most examples I have seen.

After that we will need a few claims to put in the token, otherwise why would we need a token:

var claimsIdentity = new ClaimsIdentity(new List<Claim>()
{
    new Claim(ClaimTypes.NameIdentifier, "myemail@myprovider.com"),
    new Claim(ClaimTypes.Role, "Administrator"),
}, "Custom");

Now we can create the security token descriptor:

var securityTokenDescriptor = new SecurityTokenDescriptor()
{
    AppliesToAddress = "http://my.website.com",
    TokenIssuerName = "http://my.tokenissuer.com",
    Subject = claimsIdentity,
    SigningCredentials = signingCredentials,
};

Please note that the AppliesToAddress and TokenIssuerName must be valid URI’s. Not in the sense that they should be resolvable, but they must be in a valid URI format (if you have accidentally read the v3.5 WIF documentation this can be confusing, it says that any string will do). The AppliesToAddress should contain the token’s audience, which means the website or application that will receive te token. The TokenIssuerName is the application issuing the token obviously.

This token descriptor can now be used with any WIF (Windows Identity Foundation) token handler (see the SecurityTokenHander class MSDN help). The JwtSecurityTokenHandler we are going to use is a descendant from that class (and implements the necessary abstract members).

Here is the code to create a token, then sign and encode it:

var tokenHandler = new JwtSecurityTokenHandler();
var plainToken = tokenHandler.CreateToken(securityTokenDescriptor);
var signedAndEncodedToken = tokenHandler.WriteToken(plainToken);

If you want you can print the stuff on the screen now to see what it generated:

Console.WriteLine(plainToken.ToString());
Console.WriteLine(signedAndEncodedToken);
Console.ReadLine();

Now that we have the encoded token that is easily transportable we might want some other application to validate the token (to see that it was not tampered with). To do this, we first need an instance of the TokenValidationParameters class:

var tokenValidationParameters = new TokenValidationParameters()
{
    ValidAudiences = new string[]
    {
        "http://my.website.com",
        "http://my.otherwebsite.com"
    },
    ValidIssuers = new string[]
    {
        "http://my.tokenissuer.com",
        "http://my.othertokenissuer.com"
    },
    IssuerSigningKey = signingKey
};

As you can see, the TokenValidationParameters class allows us to specify multiple valid issuers and audiences. You will also need to specify the same signing key as when you created the token (obviously). We can now simply validate the token the following way:

SecurityToken validatedToken;
tokenHandler.ValidateToken(signedAndEncodedToken,
    tokenValidationParameters, out validatedToken);

Console.WriteLine(validatedToken.ToString());
Console.ReadLine();

You might be wondering how the token handler knows which signature and digest algorithms should be used. However if you look carefully you will see that the algorithm name is encoded into the token (this encoding is simply Base64, not encrypted).

The source code to this sample can be found here.

Problems with OAuth Access Token encryption and decryption using Microsoft.OWIN hosted in IIS.

If you want to secure access to your WebAPI calls, a mechanism you can use is OAuth2 Bearer tokens. These tokens are generated via a login call for instance, and the website or mobile app can hold on to this token to authenticate with the server. These tokens can be generated using Microsoft’s OWIN implementation (also known as Katana).

These tokens have an expiration date. After that date you won’t accept the token obviously. However there are also some situations that can occur where the token can’t even be decrypted.

First of all, the default way of encrypting the token when you host the Owin/Katana in your own process (HttpListener or otherwise) is different from when it is being hosted in IIS using the SystemWeb host (which is a separate NuGet package btw). The former uses the DPAPI to protect the tokens, while the latter uses ASP.NET’s machine key data protection. There is also the option of providing your own provider/format.

I am currently only familiar with the SystemWeb host under IIS, and we recently ran into some problems after updating our software and moving it to another machine. See, we had these mobile devices who registered with our WebAPI service and stored a token which should not expire. However, after the update we found the tokens would not decrypt anymore and our users were presented with a security error, which meant they had to reregister the device with our software.

We quickly found out that we forgot to set the machine key in our web.config so encryption on the new server was different than the old one. However after configuring our web.config to use the same machine key as the old server tokens were still not being decrypted.

After a lot of searching it turned out that Microsoft.Owin 3.0.1 will not decrypt tokens created by Microsoft.Owin 3.0.0. As soon as we downgraded all our Microsoft.Owin packages back to 3.0.0 version it worked again.

To make a long story short:

Make sure both machine key and Microsoft.Owin versions stay the same if you want your tokens to keep working after an update of your software. Otherwise you find out the hard way why you should probably have used your own token encryption/decryption scheme in the first place. Our next order of business is finding a way to update our Microsoft.Owin version in the future without breaking our current user’s device registrations.