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.
Hi there, where can I get the source code? I get a 404 trying to reach the page.
Much appreciated!
Thanks!!!
Hi,
How do i add some custom claims to the token, example, i want to add “APPVERSION” to the token, how can i do that?
Regards,
I know this is a really (really really) late reply to this, but I thought i’d still answer it anyway. To add your own custom claims you can just add a new claim to the ClaimsIdentity. the Claim constructor takes 2 strings as parameter, and you are free to replace the ClaimTypes.Role or ClaimTypes.NameIdentifier with any string you like. I should point out however that the original ClaimTypes are URLs. For instance the ClaimTypes.NameIdentifier is actually just the string “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier”. This might be really annoying if you want to keep your token small. So I keep my custom claim types very short (like 3 to 8 characters).
Hi there, this is a fantastic write-up for doing symmetric signing on JWT. Do you also have any tutorials on how to do JWT signing with private keys and verification with public keys?
Much appreciated if you can post a sample!
This blog has been extremely helpful. It removed all the clutter and is to the point.
Thanks
Hi,
I know this is pretty late to ask, but please correct me if i am missing something here.
When I try to pass the SecurityTokenDescriptor to tokenHandler.CreateToken, I am getting an error saying that the securityTokenDescriptor is from System.IdentityModel whereas it is expecting Microsoft.IdentityModel .. Please correct me if I am doing something wrong in here..
TIA
This is because Microsoft changed the namespaces between WiF 3.5 and WiF 4.5 (in .NET Framework 4.5 WiF has been included and before that it was a separate thingy). So you are probably targeting a pre 4.5 framework version. I actually don’t know if the above solution can be easily converted to WiF 3.5.
Some remarks / questions.
1. I needed to add an extra reference i.e. System.IdentityModel you did not mention.
2. I have the same reference you have and still JwtSecurityTokenHandler is not know. I added
using System.IdentityModel.Tokens.Jwt;
But I get an error that securityTokenDescriptor is not convertable from System.IdentityModel.Tokens.SecurityTokenDescriptor to Microsoft.IdentityModel.Tokens.SecurityDescriptor.
I’m using this in an MVC application.
Any suggestions ?
This is because Microsoft changed the namespaces between WiF 3.5 and WiF 4.5 (in .NET Framework 4.5 WiF has been included and before that it was a separate thingy). So you are probably targeting a pre 4.5 framework version. I actually don’t know if the above solution can be easily converted to WiF 3.5.
This problem was fixed for me by targeting framework 4.5.2 instead of 4.5.1. Manually remove all references and package config references to any Microsoft namespaces.
Thanks for a very nice and concise tutorial. Much appreciated.
Hi,
I have made changes as instructed, but still having same problem. Please help.
There is a post in StackOverflow which explains what to do to resolve the references problem
http://stackoverflow.com/questions/38231321/error-trying-to-generate-token-using-net-jwt-library
Good post! How a former colleague can help 🙂
For those who don’t know, you can verify a token quickly here: https://jwt.io/
The secret text from the sample code: “This is my shared, not so secret, secret!” can be pasted (without the quotes) to verify the signature.
Hi, this is good! thx.
Is there a .net core version? 🙂
Pingback: JSON Web Token (JWT) with Web API – Humble Bits
How would you modify this code to use a secret that is encoded in Base-64?
Thanks again for your great writeup!
I figured out my own answer – I have to first convert the base 64 secret string back to regular text as follows:
byte[] data = Convert.FromBase64String(base64SecurityKey);
var plainTextSecurityKey = Encoding.UTF8.GetString(data);
Thanks again!
Hello!
I have a service developed in C # and the framework I have used for it to be able to run on server 2003 is .net 4.0, and I do not know how to do to generate a token and check it out after it is validated.
Helpe me please,
Link for response
https://stackoverflow.com/questions/46515101/how-to-generate-token-in-c-sharp-and-validate-jwt-in-net-4-0
Clean and concise, you made my day.
Thank you very much!
I think this is outdated.
InMemorySymmetricSecurityKey is not defined in version 5.15 System.IdentityModel.Tokens.
SigningCredentials does not contain a constructor that takes 3 arguments
A lot of things have changed in System.IdentityModel.Tokens since i’ve written this post. I’m afraid I currently don’t have the time to see if I can refactor it to work with the newer version.
I was able to use Microsoft.IdentityModel.Tokens.SymmetricSecurityKey