JSON Web Token (JWT)

Is a way to authenticate a user or a client with a server

Workflow

Step 1: User logs in (username/password)

client sends:

POST /login HTTP/1.1
Host: example.com
Content-Type: application/json

{
	"username": "Mustafa",
	"password": "password123"
}

server responds:

HTTP/1.1 200 OK
Content-Type: application/json

{
	"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtdXN0YWZhIiwiaWF0IjoxNjg1NTMyMDAwLCJleHAiOjE2ODU1MzIzNjB9.4tOzQVk1..."
}

Step 2: Client stores this token in a local storage or memory and uses it in future requests to authenticate without the need to login is using credentials again.

Step 3: Client accesses a protected resource, sending the token

client sends:

GET /protected-resource HTTP/1.1
Host: example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtdXN0YWZhIiwiaWF0IjoxNjg1NTMyMDAwLCJleHAiOjE2ODU1MzIzNjB9.4tOzQVk1...

Now the server validates the token by checking the signature to ensure the token is valid. It also checks expiration to make sure token is not expired and it extracts data to identify the user.

server responds:

HTTP/1.1 200 OK
Content-Type: application/json
{
	"data": "This is protected data for user mustafa"
}

If the token is missing, invalid, or expired, server responds with 401

HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
	"error": "Invalid or expried token"
}

Token structure

The JWT token encodes information in three base64 parts - header, payload, and signature.

A JWT looks like this (3 parts separated by dots):

xxxxxxx.yyyyyy.zzzzzz
  • Header: contains metadata about the token
    {
      "alg": "HS256",  // Algorithm used for signature (HMAC SHA-256 here)
      "typ": "JWT"     // Token type
    }
  • Payload (Claims): contains statements about the user and token. Common claims are subject (user id or username), iat (issued at timestamp), exp (expiration timestamp), custom claims (e.g., roles, permission)
    {
      "sub": "mustafa",
      "iat": 1685532000,
      "exp": 1685532360,
      "role": "admin"
    }
  • Signature: the signature is generated by:
    HMACSHA256(
    	base64UrlEncode(header) + "." + base64UrlEncode(payload),
    	secret_key
    )

    The signature proves the token was created by a trusted party (server keeps the secret key) and was not altered.