JWT Tokens Explained: How They Work and When to Use Them

JSON Web Tokens have become the standard for stateless authentication. Learn how they work, when to use them, and how to avoid common security pitfalls.

What is a JWT?

The weird thing about JWTs is that they're not encrypted by default — they're just base64-encoded. Anyone who intercepts your token can read the payload. The signature stops tampering, but your claims are fully visible. That surprises a lot of people who assumed "token" meant "secret."

JWTs are defined in RFC 7519 and have become the de facto standard for token-based authentication in modern web applications, particularly in single-page applications (SPAs), mobile apps, and microservices architectures.

JWT Structure

A JWT consists of three parts separated by dots (.):

  1. Header: Contains metadata about the token, including the type and signing algorithm
  2. Payload: Contains the claims (statements about the user and additional data)
  3. Signature: Verifies the token hasn't been tampered with

Here's what a JWT looks like:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The Header

The header typically contains two pieces of information: the type of token (JWT) and the signing algorithm being used (like HMAC SHA256 or RSA). When decoded, it looks like:

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

The Payload

The payload contains the claims. Claims are statements about an entity (typically the user) and additional metadata. There are three types of claims:

  • Registered claims: Predefined claims like iss (issuer), exp (expiration time), sub (subject), aud (audience)
  • Public claims: Custom claims that should be registered to avoid collisions
  • Private claims: Custom claims created for sharing information between parties
{
    "sub": "1234567890",
    "name": "John Doe",
    "email": "john@example.com",
    "role": "admin",
    "iat": 1516239022,
    "exp": 1516242622
}

The Signature

The signature is created by taking the encoded header, encoded payload, a secret, and signing it with the algorithm specified in the header. This ensures the token hasn't been modified after it was issued.

Security Warning

The header and payload are only Base64Url encoded, not encrypted. Anyone can decode them. Never put sensitive information like passwords in a JWT. The signature only ensures integrity, not confidentiality.

How JWT Authentication Works

Here's the typical authentication flow with JWTs:

  1. User logs in: The user sends credentials (username/password) to the server
  2. Server validates: The server verifies the credentials against the database
  3. Token issued: Upon successful authentication, the server creates a JWT and returns it
  4. Client stores token: The client stores the JWT (typically in localStorage or memory)
  5. Subsequent requests: The client includes the JWT in the Authorization header for API requests
  6. Server validates token: The server validates the JWT signature and grants access

When to Use JWTs

JWTs are ideal for:

  • Single Sign-On (SSO): JWTs are widely used across different domains
  • Mobile applications: Stateless authentication works well for mobile apps
  • Microservices: Services can validate tokens without contacting an auth server
  • APIs: Stateless authentication is simpler for REST APIs

Security Best Practices

  • Use HTTPS: Always transmit JWTs over HTTPS to prevent interception
  • Set short expiration times: Use short-lived tokens (15 minutes to 1 hour) and implement refresh tokens
  • Validate all claims: Check issuer, audience, and expiration time
  • Use strong secrets: For HMAC, use long, random secrets. For RSA, use proper key sizes
  • Don't store sensitive data: Remember, payloads are readable by anyone with the token
  • Implement token revocation: Have a strategy for invalidating tokens when needed

Common JWT Libraries

Most languages have mature JWT libraries:

  • JavaScript/Node.js: jsonwebtoken, jose
  • Python: PyJWT, python-jose
  • Java: jjwt, auth0-java-jwt
  • .NET: System.IdentityModel.Tokens.Jwt
  • Go: golang-jwt/jwt

Try Our JWT Decoder

Decode and inspect JWT tokens safely in your browser. No data is sent to any server.

Open JWT Decoder

Conclusion

JWTs provide a powerful, flexible way to handle authentication in modern applications. Their self-contained nature makes them ideal for distributed systems and stateless architectures. However, they require careful implementation to maintain security. Always use established libraries, follow security best practices, and understand the trade-offs involved in token-based authentication.