DEV Community

Cover image for JWT: The Secret Code for Web Security 🔐
Priya
Priya

Posted on • Updated on

JWT: The Secret Code for Web Security 🔐

Imagine your web application is a party, and you need a way to ensure only the right guests get in. That’s where JSON Web Tokens (JWT) come in—they act like VIP passes, ensuring that only authorized guests (users) gain access!

What is JWT?

JWT stands for JSON Web Token. It’s a compact, secure way to transmit information between two parties. Think of it as a special code that proves someone is who they claim to be and guarantees that the information hasn’t been tampered with.

We previously discussed why basic authentication isn’t the safest option. For a quick refresher, check out my previous post.

JWT Breakdown: What’s Inside?

Let’s break down the three main parts of a JWT:

JWT format
Image credit: Michał Sajdak

1. Header

The header typically consists of two parts:

  • alg: The algorithm used to sign the token, such as HMAC SHA256 (HS256).
  • typ: The type of token, which is usually JWT.

Example:

{
  "alg": "HS256",
  "typ": "JWT"
}
Enter fullscreen mode Exit fullscreen mode

2. Payload

The payload contains the claims or statements about an entity (usually the user) and any additional data. Common claims include:

  • sub: Subject of the token (usually a unique identifier for the user).
  • name: Name of the user.
  • iat: Issued At, indicating when the token was issued.

Example:

{
  "sub": "1234567890",
  "name": "Priya",
  "iat": 1516239022
}
Enter fullscreen mode Exit fullscreen mode

3. Signature

The Signature is like a secret stamp that ensures the token’s legitimacy. It’s used to verify that the sender of the JWT is who it claims to be and that the message hasn't been tampered with. It’s created by encoding the header and payload, then signing them with a secret key.

Example:

HMACSHA256(
  BASE64URL(header) + "." + BASE64URL(payload),
  secret
)
Enter fullscreen mode Exit fullscreen mode

BASE64URL - Base64URL encoding is a variant of Base64 encoding designed to be URL-safe. It is used in JWTs to ensure that the encoded data is safe for inclusion in URLs.

JWT Representation: The Three Parts

When you put it all together, a JWT looks like this:

  • Header (blue) comes first.
  • Payload (green) is second.
  • Signature (red) is last.

Each section is encoded and concatenated with dots to form the complete JWT. This structure ensures each part can be easily identified and processed.


Signing Algorithms: Symmetric vs. Asymmetric

Symmetric vs. Asymmetric
Image credit: ByteByteGo

1. Public Key / Asymmetric

Asymmetric signing uses a pair of keys: a private key to sign the JWT and a public key to verify it. Common asymmetric algorithms include RS256 (RSA).

How It Works:

  • Two Keys: The private key signs the JWT, while the public key is used for verification.
  • Separation of Responsibilities: Only the server holding the private key can sign tokens, and anyone with the public key can verify them.
  • Enhanced Security: Since the signing key (private key) is kept secret and verification uses the public key, it’s harder for attackers to forge tokens.

2. Symmetric

In symmetric signing, the same secret key is used for both signing and verifying the JWT. The most commonly used symmetric algorithm is HMAC SHA256 (HS256).

How It Works:

  • Single Key: Both the server generating the JWT and the server verifying it use the same key.
  • Simplicity: This method is easy to set up, involving just one secret key that must be securely shared and stored.

Which One to Choose?

  • Symmetric: Best suited for scenarios where both signing and verification occur within a trusted environment.
  • Asymmetric: Ideal for distributed systems where multiple services need to verify tokens, but only the authorization server should sign them. This is commonly used for public APIs and microservices architecture that involve third-party verification.

How is a JWT Created?

Here’s how JWTs are typically created:

1. User Logs In

The user sends their login credentials (username and password) to the server via a POST request.

Example:

POST /login
Content-Type: application/json

{
  "username": "priya",
  "password": "yourPassword"
}
Enter fullscreen mode Exit fullscreen mode

2. Server Authenticates the User

The server checks the provided credentials against stored data (typically in a database). If valid, the user is authenticated.

3. Create the JWT

The server creates the JWT by:

  • Creating the Header: Define the algorithm and token type.
  • Creating the Payload: Add user information.
  • Signing the JWT: Combine and sign the header and payload with a key.

4. Send the JWT to the User

The server sends the JWT back to the client as part of the HTTP response. The client typically stores this token in localStorage, sessionStorage, or a secure HTTP-only cookie.

Example:

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

{
  "token": "<your_jwt_token>"
}
Enter fullscreen mode Exit fullscreen mode

5. Client Uses the JWT for Subsequent Requests

For protected endpoints, the client includes the JWT in the Authorization header.

Example:

GET /protected-endpoint
Authorization: Bearer <your_jwt_token>
Enter fullscreen mode Exit fullscreen mode

How is a JWT Verified?

JWT verification involves checking the token's validity and ensuring the payload hasn’t been tampered with. Here’s how:

1. Server Receives and Decodes the JWT

  • Decode the Header and Payload to understand the token’s content.
  • The Signature is verified but not decoded directly.

2. Verify the Signature

  • Reconstruct the data from the Header and Payload: base64UrlEncode(header) + "." + base64UrlEncode(payload).
  • Apply the same hashing algorithm specified in the Header using the secret key (for HS256) or the public key (for RS256).
  • Compare the newly generated signature with the one included in the JWT. If they match, the token is valid and untampered.

3. Validate Claims

  • Expiration (exp): Check if the token has expired by comparing the exp claim with the current time.
  • Subject (sub): Ensure the subject claim matches the intended user or entity.

4. Use the Payload Data

  • If the token is valid, the payload can be used to authenticate the user or perform authorized actions.

5. Handle Verification Failures

  • If any checks fail (e.g., signature mismatch, expiration), reject the token and return an appropriate error (e.g., 401 Unauthorized).

Wrapping Up

Congrats! 🎉 You've just unlocked the power of JWTs for securing your web apps. Whether you're leaning towards symmetric simplicity or asymmetric security, JWTs are here to keep your APIs safe.

Ready for more? In the next blog, we’ll dive into using JWTs with Spring Security to make them even more powerful.

Want to Learn More?
🛠 Play with JWTs and see how they work.
🕵️‍♀️ Hacksplaining helps you understand security better.

Stay tuned—next up, we’re making JWT magic happen with Spring Security! 🔒 Feel free to share your thoughts or ask questions in the comments below.

Top comments (0)