JWT

JSON Web Token is a specification that defines a way to sign and exchange information.

Like signed cookies the information can be verified and trusted, but not encrypted, so it not for sensitive information.

The Format

JWT consist of 3 parts:

<header>.<payload>.<signature>

Both header and payload are JSON strings that encode as base64 strings.

Header contains two fields, signing algorithm and type:

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

Payload

Payload contains the actual data, and also some standard fields like exp(expiration time) and sub(subject).

{
  "exp": 17266579863,
  "sub": "<user id>",
  "name": "Alice"
}

All standard field name are shortened to 3 chars to save space. (But json is not a concise format anyway.)

Signature

Signature is computed as following:

HMACSHA256(base64(header) + '.' + base64(payload), secret)

Signing

A minimal implementation:

const crypto = require(crypto)

function generateJWT(payload, secretKey) {
  const header = {
    alg: 'HS256',
    typ: 'JWT'
  }

  const encodedHeader = btoa(JSON.stringify(header))
  const encodedPayload = btoa(JSON.stringify(payload))

  const signature = crypto.createHash('sha256', secretKey)
    .update(`${encodedHeader}.${encodedPayload}`)
    .digest('base64')

  return `${encodedHeader}.${encodedPayload}.${signature}`;
}

Verification

Just sign again and compare the signature. The exp value should also be compared with current timestamp.

Expiration

Token with expration is much securer. The sub in Payload is designed for this purpose. It should a epoch time in the future.

Revoke a Token

The is no way to revoke a JWT, but you can mantain a blacklist in a kv store or database, and better load it into memory for efficiency.