Jordan Savant # Software Engineer

JSON Web Tokens (JWT)

JWT's are a way to create a permissions string that can identify the permissions of an entity across multiple systems.

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. It is a URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

It consists of a header, payload and signature represented with JSON and base64 encoded strings.

Header

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
$secret = "somePassword";
$header64 = base64encode($header);
$payload64 = base64encode($payload64);
$signature = sha256($header64 . "." . $payload64 . "." . $secret);

$jwt = "$header64.$payload64.$signature";

Used in Authentication

After a user is logged in every subsequent request will include the JWT to allow them to access routes and resources that are permitted with that token.

Single Sign On uses JWT because of its small overhead and ability to be used across several domains.

Used in Information Exchange

JWT's can be signed with public/private key pairs which will ensure that the senders are who they say they are. As well, the payload of the tranmission can be confirmed by calculating the signature from the header.

Structure

A JWT consists of three parts separated by a dot (.) which are: Header, Payload and Signature.

So it looks like hhhhhh.ppppppp.sssss

Header

JSON object consisting of two parts: type of token, which is "JWT", hashing algorithm used.

An example

{
    "alg": "HS256",
    "typ": "JWT"
}

This is then base64 encoded into to form the first part of the JWT.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

The core of the JWT, these consist of claims. Claims are statements about an entity, such as a user, and additional metadata that support those claims. There are three types of claims: registered, public and private.

Registered Claims

Registered claims are official claims registered in the standard. They are not mandatory but a good starting point.

  • "iss" (Issuer) Claim
    • identifies the principal that issued the JWT
    • value is a case-sensitive string containing a StringOrURI value
  • "sub" (Subject) Claim
    • identifies the principal that is the subject of the JWT.
    • claims in a JWT are normally statements about the subject.
    • subject value MUST either be scoped to be locally unique in the context of the issuer or be globally unique.
    • value is a case-sensitive string containing a StringOrURI value
  • "aud" (Audience) Claim
    • identifies the recipients that the JWT is intended for.
    • each principal intended to process the JWT MUST identify itself with a value in the audience claim.
    • if the principal processing the claim is not in "aud" it should be rejected
    • value is an array of case-sensitive strings, each containing a StringOrURI value.
  • "exp" (Expiration Time) Claim
    • identifies the expiration time on or after which the JWT MUST NOT be accepted for processing.
  • "nbf" (Not Before) Claim
    • cannot be accepted before this time
  • "iat" (Issued At) Claim
    • the time at which the JWT was issued.
  • "jti" (JWT ID) Claim
    • unique identifier for the JWT
    • can be used to prevent the JWT from being replayed

Public Claims

These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.

Private Claims

These are the custom claims created to share information between parties that agree on using them and are neither registered or public claims. Basically, these are the ones used by your application specific use case.

Example payload

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

This is then base64 encoded to form the second part of the JWT.

eyJzdWIiOiAiMTIzNDU2Nzg5MCIsIm5hbWUiOiAiSm9obiBEb2UiLCJhZG1pbiI6IHRydWV9

Signature

This is how the JWT is confirmed as legitimate. To create the signature you take the encoded header, encoded payload, a secret, the algorithm specified in the header and sign it.

Here is an example creating the signature with sha256 hashing algorithm:

$signature = sha256(base64encode($header) . "." . base64encode($payload) . "." . $secret);

Combining JWT

Take the encoded header, encoded payload and the hashed signature and combine them separated with . period characters.

Header

{
  "alg": "HS256",
  "typ": "JWT"
}

Payload

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
$secret = "somePassword";
$header64 = base64encode($header);
$payload64 = base64encode($payload64);
$signature = sha256($header64 . "." . $payload64 . "." . $secret);

$jwt = "$header64.$payload64.$signature";

Using in Authentication

The user makes an initial login and the JWT is created by the server and saved in the users local storage. Each successive operation passes the JWT in the Authorization header of the request.

Authorization: Bearer <token>

A session is no longer necessary to be maintained on the server. A stateless API can be used and each request JWT is validated against the claims it makes. In addition, any disparate services with the same authentication routine can use the same JWT for access. No longer does the session need to be spread across multiple API's, servers or services because a single JWT can be sent to each one.

It is then possible to have an authentication service that validates claims from a JWT that your existing servers and services trust. A single authorization service allows for single sign on.