Understanding JWTs for API Authentication
A clear and concise guide to JSON Web Tokens (JWTs). Learn what they are, how they work, and why they are the standard for securing modern, stateless APIs.
In the world of modern web development, especially with the rise of single-page applications (SPAs) and microservices, you'll constantly encounter the term JWT, which stands for JSON Web Token. JWTs (pronounced "jot") have become the de facto standard for securing APIs because they enable a secure and stateless way to handle authentication.
Let's break down what they are and how they work.
What is a JWT?
A JWT is a compact, URL-safe means of representing claims to be transferred between two parties. In simpler terms, it's a string of characters that contains a set of claims (information) as a JSON object. This string is digitally signed, so the recipient can verify that it's authentic and hasn't been tampered with.
A JWT looks like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
This string is not random; it's composed of three parts, separated by dots (.
):
- Header: Contains metadata about the token, like the signing algorithm used.
- Payload: Contains the claims. These are statements about an entity (typically, the user) and additional data.
- Signature: A cryptographic signature that verifies the integrity of the token.
Let's look at each part.
1. The Header
The header is a simple JSON object that is Base64Url encoded. It typically consists of two parts:
alg
: The signing algorithm being used (e.g.,HS256
for HMAC with SHA-256).typ
: The type of the token, which is alwaysJWT
.
{
"alg": "HS256",
"typ": "JWT"
}
2. The Payload
The payload is another Base64Url encoded JSON object that contains the claims. Claims are the heart of the JWT. There are a few standard, registered claims:
sub
(Subject): The identifier of the user (e.g., a user ID).iss
(Issuer): Who issued the token.exp
(Expiration Time): The timestamp after which the token is no longer valid. This is a crucial security feature.iat
(Issued At): When the token was issued.
You can also add your own public or private claims to include any information you need, like a user's roles or permissions.
{
"sub": "user-123",
"name": "Alice",
"roles": ["admin", "editor"],
"exp": 1678886400
}
Important: The header and payload are just Base64Url encoded, not encrypted. Anyone can decode them and read their contents. Therefore, you should never put sensitive information in the payload of a JWT.
3. The Signature
This is the most critical part for security. The signature is created by taking the encoded header, the encoded payload, a secret key (that only the server knows), and signing them with the algorithm specified in the header.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
your-256-bit-secret
)
When your API receives a JWT from a client, it performs the same signature calculation using the secret key it has stored. If the signature it generates matches the signature on the token, it proves two things:
- Authenticity: The token was issued by a trusted source (because only the trusted source has the secret key).
- Integrity: The header and payload have not been changed since the token was signed.
The Authentication Flow
- A user logs in to your application with their credentials (e.g., username and password).
- The server validates the credentials. If they are correct, the server generates a JWT containing the user's ID and an expiration time, and signs it with its secret key.
- The server sends this JWT back to the client.
- The client stores the JWT (typically in memory or local storage).
- For every subsequent request to a protected API endpoint, the client includes the JWT in the
Authorization
header, usually with theBearer
scheme:Authorization: Bearer <token>
. - The API receives the request, extracts the token, and validates the signature. If the signature is valid and the token has not expired, the API trusts the claims in the payload and processes the request.
Why JWTs are Great for Modern APIs
This flow is stateless. The server does not need to store any information about the user's session in a database or cache. All the information it needs to verify the user is contained within the token itself. This makes it incredibly easy to scale your application, as any instance of your API can validate a token without needing to access a shared session store.
Conclusion
JWTs are a powerful and elegant solution for securing modern, stateless APIs. By understanding their three-part structure—the header, the payload, and the all-important signature—you can confidently build and consume APIs that are both secure and scalable.