JSON Web Tokens

An authentication server provides a client with a JSON Web Token, and the authentication server will also handle requests from application servers to verify tokens supplied by clients.

Algorithm

Generally, the token generation code follows this process:

  1. Initialise the token header as a set of JSON objects.
  2. Initialise the token payload as a set of JSON objects.
  3. Base64-encode the header and payload independently. This gives us the unsigned token.
  4. Using the HMAC SHA256 algorithm, and a secret key value, generate the signature for the unsigned payload.
A token, therefore, will have three segments: a) header, b) payload, and c) signature. The first two are Base64-encoded JSON objects, and the third is the encoded signature of the first two segments. This can be seen in action when generating a token with the debugger at jwt.io:

https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
When decoded, the token would look something like this:

{ "alg": "HS256", "typ": "JWT" }
{ "sub": "Web Application", "name": "Michael", "iat": 45435334 }
{ SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c }

.NET Implementation

When working with .NET, one could use System.IdentityModel.Tokens.Jwt, but it can also be done using Newtonsoft.Json and System.Security.Cryptography.

I defined the header properties in a TokenHeader class:

public class TokenHeader
{
public string alg { get; set; }
public string typ { get; set; }
}
Instantiating the TokenHeader class in the main method, we can declare static variables for the objects:

TokenHeader tokenHeader = new TokenHeader();
tokenHeader.alg = "HS256";
tokenHeader.typ = "JWT";
The variables are formatted as JSON objects, then Base64-encoded:

string headerString = JsonConvert.SerializeObject(tokenHeader);
string encodedHeaderString = ConvertHeaderToJson(headerString);


private static string ConvertHeaderToJson(string headerString)
{
byte[] headerStringAsBytes = Encoding.ASCII.GetBytes(headerString);
string encodedHeaderString = Convert.ToBase64String(headerStringAsBytes);
return encodedHeaderString; }
For generating the third segment of the token – the signature – the process is different. In this case, we need to generate a hash digest of the header and payload, along with a 256-bit secret value, then encode that digest. The algorithm for this is given as:

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), your-256-bit-secret)
This algorithm is implemented by the following code:
string message = encodedHeaderString + "." + encodedPayloadString;
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(myKey);

HMACSHA256 hmacsha256 = new HMACSHA256(keyByte);

byte[] messageBytes = encoding.GetBytes(message);
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
string hashAsString = BitConverter.ToString(hashmessage);

byte[] signatureStringAsBytes = Encoding.ASCII.GetBytes(hashAsString);
string encodedSignature = Convert.ToBase64String(signatureStringAsBytes);
return encodedSignature;

JavaScript Implementation

Several JavaScript libraries are needed for the implementation here. The crypto ones are referenced on Joe Kampschmidt’s blog: To initialise the header and payload as JSON objects, JSON.parse() is used.

var headerjson = '{ "alg": "HS256", "typ": "JWT" }',
headerobj = JSON.parse(headerjson);

var payloadjson = '{ "sub": "x555", "name": "Michael", "iat": 445644543534, "issued": ' + Math.floor(Date.now() / 1000) + ' }',
payloadobj = JSON.parse(payloadjson);
Next, independently encode the header and the payload:

headerb64 = btoa(unescape(encodeURIComponent(headerjson)));
headerb64str = decodeURIComponent(escape(window.atob(headerb64)));

payloadb64 = btoa(unescape(encodeURIComponent(payloadjson)));
payloadb64str = decodeURIComponent(escape(window.atob(payloadb64)));
The unsigned token will consist of two segments, one for the encoded header and the other the encoded payload:
var unsignedToken = headerb64 + "." + payloadb64;


Finally, the crypto libraries provide the HMAC SHA256 algorithm used here for signing the token:

var secretKey = "Password1";
var tokenSignature = CryptoJS.HmacSHA256(unsignedToken, secretKey);
var encodedTokenSignature = CryptoJS.enc.Base64.stringify(tokenSignature);
gentoken.value = encodedTokenSignature;
And finaly, I’ve put all three segments together to form the signed token:
allsegments.value = headerb64 + "." + payloadb64 + "." + encodedTokenSignature;