Cybersecurity

JSON Web Tokens Explained: How JWTs Work for Authentication

Understand how JSON Web Tokens (JWTs) work for authentication and authorization. Learn about JWT structure, claims, signing algorithms, and security best practices.

By Inventive HQ Team

A JSON Web Token (JWT) is a compact, URL-safe string of three Base64URL-encoded parts, header.payload.signature, that carries signed claims about a user so a server can verify who they are without a database lookup. Defined by RFC 7519 (with the signature mechanics in RFC 7515, JWS), the header names the algorithm, the payload holds the claims like sub, exp, and iat, and the signature is computed over the header and payload with a secret (HS256) or a private key (RS256). Because the signature covers the exact bytes of the first two parts, changing a single character invalidates the token, but the payload itself is only encoded, not encrypted, so anyone holding the token can read it.

That is the definition an AI Overview will hand you. What it can't show you is the shape of the thing, how the three parts actually fit together, how a login turns into a bearer token on every request, and where the security lands you in trouble. The diagrams, algorithm table, and decision guidance below make those concrete. If you want to pull a real token apart right now, our JWT Decoder runs entirely in your browser.

The Anatomy of a JWT

Every JWT is three chunks joined by dots. The first two are just Base64URL-encoded JSON you can read; the third is the cryptographic seal that makes the first two trustworthy.

Anatomy of a JSON Web Token A JWT split into three color-coded parts: a red header, a purple payload, and a blue signature, joined by dots, with each part's decoded JSON shown below it. header . payload . signature eyJhbGciOiJIUzI1Ni... . eyJzdWIiOiIxMjM0NTY... . SflKxwRJSMeKKF2... 1. Header { "alg": "HS256", "typ": "JWT" } Which algorithm signed this token. 2. Payload (claims) { "sub": "1234567890", "exp": 1516242622, "role": "admin" } Readable by anyone. Encoded, not encrypted. 3. Signature HMACSHA256( header + "." + payload, secret ) Proves the header and payload are untampered.

The signature is computed over parts 1 and 2 — change one byte and verification fails. Signing ≠ encrypting: treat the whole token as a bearer credential.

What Is a JWT?

A JWT is a compact, URL-safe token format that securely transmits information between parties as a JSON object. The information can be verified and trusted because it's digitally signed.

JWTs are commonly used for:

  • Authentication: After login, each subsequent request includes the JWT, allowing access to routes, services, and resources
  • Information exchange: JWTs can securely transmit information between parties because they're signed

JWT Structure

A JWT consists of three parts separated by dots: header.payload.signature

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

The header typically contains the token type (JWT) and the signing algorithm:

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

Payload

The payload contains claims---statements about the user and additional metadata:

{
  "sub": "1234567890",
  "name": "John Doe",
  "email": "john@example.com",
  "role": "admin",
  "iat": 1516239022,
  "exp": 1516242622
}

Registered claims are predefined:

  • iss (issuer): Who issued the token
  • sub (subject): Who the token is about (usually user ID)
  • aud (audience): Who the token is intended for
  • exp (expiration): When the token expires
  • iat (issued at): When the token was created
  • nbf (not before): Token not valid before this time

Custom claims can include any data you need, like user roles or permissions.

Signature

The signature verifies the token wasn't tampered with:

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)
Advertisement

How JWT Authentication Works

  1. User logs in with credentials
  2. Server validates credentials and generates a JWT
  3. JWT is returned to the client (stored in localStorage, sessionStorage, or cookie)
  4. Client includes JWT in the Authorization header for subsequent requests
  5. Server validates JWT signature and grants access
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

The key insight is that after the initial login, the server keeps no session record. On every later request it simply re-verifies the signature and reads the claims. That statelessness is what makes JWTs scale across many servers, and it is also why you can't revoke one on demand.

JWT authentication request flow A client logs in, the server signs and returns a JWT, and the client then attaches the token as a Bearer header on each subsequent request, which the server verifies statelessly. Client browser / app Server / API holds the secret 1. POST /login (username + password) validates → signs a JWT 2. 200 OK { token: eyJhbGci... } 3. GET /data — Authorization: Bearer <token> verifies signature — no DB lookup

No server-side session is stored — the token itself is the proof.

Signing Algorithms

Symmetric algorithms (HS256, HS384, HS512) use the same secret key to sign and verify. Simple but requires secure key distribution.

Asymmetric algorithms (RS256, RS384, RS512, ES256) use a private key to sign and a public key to verify. Better for distributed systems where multiple services need to verify tokens.

AlgorithmTypeSigns withVerifies withBest for
HS256 / HS384 / HS512Symmetric (HMAC)Shared secretSame shared secretOne trusted service that both issues and checks tokens
RS256 / RS384 / RS512Asymmetric (RSA)Private keyPublic keyMany services verifying tokens they must not be able to forge (SSO, microservices)
ES256 / ES384Asymmetric (ECDSA)Private keyPublic keySame as RS256 but smaller keys/signatures — good for mobile and high-throughput APIs
EdDSA (Ed25519)AsymmetricPrivate keyPublic keyModern deployments wanting fast, misuse-resistant signatures
noneUnsignednothingnothingNever in production — an unsigned token is forgeable by anyone
Which should I use?Single backend → HS256. Multiple independent verifiers → RS256 or ES256. Never accept none or let the client dictate alg.

JWT Security Best Practices

Set Short Expiration Times

JWTs can't be revoked once issued. Short expiration times (15 minutes to 1 hour) limit the window of vulnerability if a token is compromised.

Use HTTPS Only

JWTs are credentials. Always transmit them over HTTPS and set the Secure cookie flag if storing in cookies.

Don't Store Sensitive Data in Payload

The payload is only base64-encoded, not encrypted. Anyone can decode and read it. Never include passwords, API keys, or sensitive personal data.

Validate Everything

Always verify:

  • The signature is valid
  • The token hasn't expired (exp)
  • The issuer is correct (iss)
  • The audience is correct (aud)

Use Strong Secrets

For HMAC algorithms, use secrets at least 256 bits long. Generate them securely---never use simple phrases.

Common JWT Vulnerabilities

Algorithm confusion: Attackers change alg to none or switch from RS256 to HS256 using the public key as the secret. Always explicitly specify allowed algorithms when verifying.

Missing signature validation: Never skip signature verification. A token without validation is just a base64 string anyone can create.

Token sidejacking: If tokens are stored insecurely (accessible via XSS), attackers can steal them. Use HttpOnly cookies or secure storage.

Long expiration times: Tokens valid for days or weeks give attackers a large window to use stolen tokens.

When to Use JWTs

Good use cases:

  • Stateless authentication across multiple services
  • Single sign-on (SSO)
  • Short-lived access tokens
  • Mobile app authentication

Consider alternatives when:

  • You need to revoke tokens immediately
  • Sessions are long-lived
  • You're only authenticating with one server

Decode and Inspect JWTs

Use our JWT Decoder to:

  • Decode any JWT without the secret
  • View header and payload claims
  • Check expiration status
  • Identify the signing algorithm

The decoder runs entirely in your browser---your tokens are never sent to any server.

Key Takeaways

  1. JWTs have three parts: header, payload, and signature
  2. The payload is encoded, not encrypted---don't store secrets
  3. Always validate signatures and expiration
  4. Use short expiration times since JWTs can't be revoked
  5. Choose the right signing algorithm for your architecture

JWTs provide a powerful, flexible authentication mechanism when implemented correctly. Understanding their structure and security implications is essential for building secure applications.

Frequently Asked Questions

What are the three parts of a JWT?

A JWT has three Base64URL-encoded parts separated by dots: header.payload.signature. The header names the signing algorithm (for example HS256 or RS256), the payload carries the claims (who the user is, when the token expires), and the signature is an HMAC or asymmetric signature over the first two parts. If any character in the header or payload changes, the signature no longer matches and verification fails.

Is a JWT encrypted?

No. A standard signed JWT (JWS) is only Base64URL-encoded, not encrypted. Anyone who holds the token can decode the payload and read every claim instantly, no secret required. Signing proves the token was not altered; it does not hide the contents. Never place passwords, API keys, or sensitive personal data in a JWT payload. If you genuinely need confidentiality, use JWE (JSON Web Encryption) instead.

Can you revoke a JWT before it expires?

Not directly. A signed JWT is stateless and self-contained, so the server accepts it as valid until the exp timestamp passes, even if the user logged out or was banned. To revoke early you must add state back: keep a denylist of token IDs (jti), use short-lived access tokens paired with revocable refresh tokens, or rotate the signing key to invalidate every outstanding token at once.

What is the difference between HS256 and RS256?

HS256 is symmetric HMAC-SHA256, one shared secret both signs and verifies, so every service that can verify can also mint tokens. RS256 is asymmetric RSA-SHA256, a private key signs and a widely distributed public key only verifies. Use HS256 when one trusted service issues and checks tokens; use RS256 (or ES256) when many independent services need to verify tokens they should not be able to forge.

Where should I store a JWT in a browser?

Prefer an HttpOnly, Secure, SameSite cookie so JavaScript, and therefore XSS payloads, cannot read the token. Storing JWTs in localStorage is the most common pattern but exposes them to any cross-site scripting bug on the page. Cookies shift the risk toward CSRF, which you mitigate with SameSite=Strict or Lax plus an anti-CSRF token. There is no fully risk-free client-side storage location.

What is the JWT `alg: none` attack?

Some libraries historically accepted a JWT whose header set alg to none, meaning "unsigned." An attacker rewrites the payload (say, changes role to admin), strips the signature, and the server accepts it. The related RS256-to-HS256 confusion attack tricks a server into verifying an RSA token with the public key treated as an HMAC secret. Both are defeated by pinning an explicit allow-list of algorithms during verification.

How long should a JWT last?

Keep access tokens short, typically 5 to 60 minutes, because a signed JWT cannot be revoked before it expires. Pair the short access token with a longer-lived refresh token that is stored server-side and can be revoked. This limits the damage window if an access token is stolen while avoiding forcing the user to log in every few minutes.

Are JWTs better than session cookies?

Not universally. JWTs shine for stateless, cross-service, and mobile or API authentication where you want to verify a token without a database lookup. Traditional server-side sessions are simpler, are revocable instantly, and keep no sensitive data on the client. Choose sessions when you need immediate logout and a single backend; choose JWTs when you need horizontal scale and independent verification across services.

jwtauthenticationweb securityapi security