Decoding and validating a JWT token using System.IdentityModel.Tokens.Jwt

I used the JWT library to decode the Json Web Token and would like to switch to the official Microsoft JWT implementation, System.IdentityModel.Tokens.Jwt .

The documentation is very scarce, so itโ€™s hard for me to figure out how to accomplish what I did with the JWT library. There is a Decode method in the JWT library that uses base64 encoded JWT encoding and turns it into JSON, which can then be deserialized. I would like to do something like this using System.IdentityModel.Tokens.Jwt, but after enough digging I can't figure out how to do this.

For what it's worth, I'm reading the JWT token from a cookie for use with Google's identity system.

Any help would be appreciated.

+67
wif jwt
Sep 07 '13 at 20:55 on
source share
2 answers

Inside the package, there is a class called JwtSecurityTokenHandler , which comes from System.IdentityModel.Tokens.SecurityTokenHandler . In WIF, this is the main class for deserializing and serializing security tokens.

The class has a ReadToken(String) method that will take your base64 encoded JWT string and return a SecurityToken that represents the JWT.

SecurityTokenHandler also has a ValidateToken(SecurityToken) method that takes your SecurityToken and creates ReadOnlyCollection<ClaimsIdentity> . Typically for a JWT, this will contain a single ClaimsIdentity object that has a set of claims representing the properties of the original JWT.

JwtSecurityTokenHandler defines some additional overloads for the ValidateToken , in particular, it has the ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters) . The TokenValidationParameters argument allows TokenValidationParameters to specify a token signing certificate (in the form of an X509SecurityTokens list). It also has an overload that accepts the JWT as a string , not a SecurityToken .

The code for this is quite complicated, but it can be found in the Global.asax.cx ( TokenValidationHandler class) code in the developerโ€™s example, called "ADAL - Native App to REST service - ACS authentication through the browser dialog" located in

http://code.msdn.microsoft.com/AAL-Native-App-to-REST-de57f2cc

As an alternative, the JwtSecurityToken class has additional methods that do not apply to the SecurityToken base class, for example, the Claims property, which receives the claims contained in it without passing through the ClaimsIdentity collection. It also has a Payload property, which returns a JwtPayload object that allows you to get the original JSON of the token. It depends on your scenario that suits him best.

The general (i.e. not JWT-specific) documentation for the SecurityTokenHandler class is in

http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.securitytokenhandler.aspx

Depending on your application, you can configure the JWT handler in the WIF pipeline just like any other handler.

There are 3 samples used in different types of applications in

http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=SearchText&f%5B0%5D.Value=aal&f%5B1%5D.Type=User&f%5B1%5D.Value=Azure% 20AD% 20Developer% 20Experience% 20Team & f% 5B1% 5D.Text = Azure% 20AD% 20Developer% 20Experience% 20Team

Probably one of them will suit your needs or, at least, will adapt to them.

+100
Sep 18 '13 at 20:59 on
source share

I'm just wondering why use some libraries to decode and verify the JWT token in general.

A designated JWT token can be created using after pseudo-code

 var headers = base64URLencode(myHeaders); var claims = base64URLencode(myClaims); var payload = header + "." + claims; var signature = base64URLencode(HMACSHA256(payload, secret)); var encodedJWT = payload + "." + signature; 

It is very easy to do without any specific library. Using the following code:

 using System; using System.Text; using System.Security.Cryptography; public class Program { // More info: https://stormpath.com/blog/jwt-the-right-way/ public static void Main() { var header = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}"; var claims = "{\"sub\":\"1047986\",\"email\":\"jon.doe@eexample.com\",\"given_name\":\"John\",\"family_name\":\"Doe\",\"primarysid\":\"b521a2af99bfdc65e04010ac1d046ff5\",\"iss\":\"http://example.com\",\"aud\":\"myapp\",\"exp\":1460555281,\"nbf\":1457963281}"; var b64header = Convert.ToBase64String(Encoding.UTF8.GetBytes(header)) .Replace('+', '-') .Replace('/', '_') .Replace("=", ""); var b64claims = Convert.ToBase64String(Encoding.UTF8.GetBytes(claims)) .Replace('+', '-') .Replace('/', '_') .Replace("=", ""); var payload = b64header + "." + b64claims; Console.WriteLine("JWT without sig: " + payload); byte[] key = Convert.FromBase64String("mPorwQB8kMDNQeeYO35KOrMMFn6rFVmbIohBphJPnp4="); byte[] message = Encoding.UTF8.GetBytes(payload); string sig = Convert.ToBase64String(HashHMAC(key, message)) .Replace('+', '-') .Replace('/', '_') .Replace("=", ""); Console.WriteLine("JWT with signature: " + payload + "." + sig); } private static byte[] HashHMAC(byte[] key, byte[] message) { var hash = new HMACSHA256(key); return hash.ComputeHash(message); } } 

Token decoding is the reverse version of the code above. To verify the signature, you will need the same and compare the signature part with the computed signature.

UPDATE: for those struggling to do base64 urlsafe encoding / decoding, see another SO question , as well as wiki and RFC

+13
Mar 22 '16 at 9:06
source share



All Articles