What is JWT? Understanding JSON Web Tokens for API Security
Have you ever wondered how apps keep your data secure while you’re logged in? JSON Web Tokens (JWTs) play a crucial role in modern authentication and authorization. In this post, we’ll break down what JWTs are, how they work, and why they’re essential for API security.
What is JWT?
JWT stands for JSON Web Token. It’s a compact, self-contained way to securely transmit information between parties. What makes JWTs particularly powerful is that they are digitally signed, making them verifiable and tamper-proof. JWTs can be signed using:
- HMAC (Hash-based Message Authentication Code) with a secret key
- RSA or ECDSA for public/private key encryption
This allows JWTs to be trusted and validated without needing to store session data on the server.
What is JWT Used For?
JWTs are widely used in modern applications for two main purposes:
1. Authorization
JWTs are commonly used for authorization, not authentication. Authentication happens when a user logs into an authentication server (Identity Provider, or IdP). Once authenticated, the server issues a JWT, which the user includes in subsequent requests to access protected resources.
2. Information Exchange
JWTs provide a secure way to exchange information between parties. Since they are signed, the recipient can verify the authenticity of the sender and ensure that the data has not been altered.
JWT Structure
A JSON Web Token consists of three parts, separated by dots (.
):
- Header
- Payload
- Signature
Together, these form a compact token like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpv
aG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
Let’s break down these components.
🚀Boost your career with Full Stack Software Developer Certificate 👉
1. Header
The header typically contains two pieces of information:
- Type (
typ
): Specifies the token type, which is JWT - Algorithm (
alg
): Defines the signing algorithm (e.g., HS256, RS256)
Example:
{
"alg": "HS256",
"typ": "JWT"
}
The header is then Base64Url encoded to form the first part of the JWT.
2. Payload
The payload contains claims, which are statements about the user or other relevant data. Claims are categorized into three types:
- Registered Claims: Predefined claims like issuer (
iss
), expiration (exp
), subject (sub
), and audience (aud
) - Public Claims: Custom claims that should use collision-resistant namespaces
- Private Claims: Claims created for communication between specific parties
Example:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
The payload is Base64Url encoded to form the second part of the JWT.
Note: JWT payloads are not encrypted, only signed. Anyone can decode and read the contents, so avoid storing sensitive information in them.
3. Signature
The signature is used to verify the authenticity of the token. It’s created by taking:
Base64Url(header) + "." + Base64Url(payload)
Then, it is signed using the algorithm specified in the header and a secret key (for HMAC) or a private key (for RSA/ECDSA).
For example, with HMAC SHA256, the signature is:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
The final JWT consists of:
Header.Payload.Signature
How JWT Works in Authentication and Authorization
While JWTs themselves are not authentication mechanisms, they play a crucial role in authorization. Here’s how they typically work:
1. User Logs In
A user logs into an authentication server (e.g., Auth0, Firebase, Cognito) using their credentials.
2. Server Issues a JWT
Once authenticated, the authentication server generates a JWT and sends it back to the user.
3. User Sends JWT with Requests
The client includes the JWT in the Authorization header when making requests to a protected API:
Authorization: Bearer <JWT>
4. Server Verifies JWT
The API server validates the JWT using the public key (for RS256) or the shared secret (for HS256). If valid, the request is processed; otherwise, access is denied.
Security Considerations for JWT
JWTs are powerful, but they must be used securely. Here are some best practices:
✅ Use Secure Algorithms
Prefer RS256 (asymmetric) or ES256 over HS256 (symmetric) to enhance security.
✅ Always Use HTTPS
Transmit JWTs over HTTPS to prevent interception.
✅ Set Expiration Times
Use short-lived tokens (exp
claim) to limit exposure in case of a token leak.
✅ Store Tokens Securely
Avoid storing JWTs in local storage as it is vulnerable to XSS attacks. Instead, use HTTP-only cookies or secure storage mechanisms.
✅ Don’t Store Sensitive Data in JWT
JWTs can be decoded easily. Never store passwords, secret keys, or personally identifiable information (PII) in them.
Real-World Example of JWT
Let’s visit jwt.io and explore an example JWT.
- A simple JWT might contain:
- Header specifying
alg: HS256
- Payload containing claims like
sub
(user ID) andiat
(issued time) - Signature generated using a secret key
- Header specifying
- A JWT issued by Auth0 will have additional fields like:
kid
(Key ID)iss
(Issuer, e.g.,https://auth0.com/
)aud
(Audience, the app this token is meant for)scope
(Permissions granted)
Conclusion
JWTs provide a stateless, scalable, and secure way to manage authorization and information exchange in modern applications. They help verify users without storing session data on the server, making them ideal for API authentication and OAuth-based access delegation.
By following best practices, you can effectively use JWTs to secure your API endpoints.
📌 Next Steps
Now that you understand how JWTs work, let’s implement them in a real-world project. Check out my next blog post, where we’ll secure a Node.js API with JWT authentication! 🚀