Skip to content
Spring Boot sb auth 5 min read

JWT Introduction

A JSON Web Token (JWT) is a compact, URL-safe token that carries a set of claims about a user, signed so the server can trust it without keeping any server-side session. JWTs are the backbone of stateless authentication in modern Spring Boot APIs: the client sends the token on every request, and the server verifies the signature instead of looking up a session. This section explains what a JWT actually contains before the later pages build a full JWT authentication flow.

What a JWT looks like

A JWT is three Base64URL-encoded parts joined by dots: header.payload.signature.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJhbGljZSIsInJvbGUiOiJBRE1JTiIsImV4cCI6MTcxODI4MDgwMH0
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Decoding the first two parts gives plain JSON. They are not encrypted — only signed — so never put secrets in a JWT.

Header — the signing algorithm and token type:

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

Payload — the claims:

{
  "sub": "alice",
  "role": "ADMIN",
  "iat": 1718277200,
  "exp": 1718280800
}

Signature — computed over the encoded header and payload using a secret or private key. If anyone tampers with the header or payload, the signature no longer matches and the token is rejected.

Claims

A claim is a single statement inside the payload. JWTs distinguish three kinds:

TypeExamplesMeaning
Registerediss, sub, aud, exp, iat, nbf, jtiStandard claims defined by the spec
Publicemail, roleCommon names, ideally collision-resistant
PrivatetenantId, planCustom claims shared between your client and server

The most important registered claims:

  • sub — the subject, usually the username or user id.
  • iss — who issued the token (your auth server’s identifier).
  • expexpiration time (epoch seconds); after this the token is invalid.
  • iat — when the token was issued.
  • aud — the intended audience (which API should accept it).
  • jti — a unique token id, useful for revocation lists.

Warning: Because the payload is only encoded, not encrypted, anyone holding the token can read every claim. Treat a JWT as readable; put only non-sensitive identifiers and authorization data in it.

Signing: HMAC vs RSA

The signature is what makes a JWT trustworthy. Two algorithm families dominate:

HMAC (HS256)RSA / EC (RS256, ES256)
Key modelOne shared secretPrivate key signs, public key verifies
Who can verifyAnyone with the secret (which can also forge)Anyone with the public key; only the holder of the private key can sign
Best forA single service that both issues and verifiesAn auth server issuing tokens that many independent services verify
Key distributionMust keep the secret on every verifierPublish the public key (often via a JWKS endpoint)

For a self-contained API where the same Spring Boot app both logs users in and validates tokens, HS256 with a strong secret is simple and secure. When an external identity provider issues tokens — like Keycloak or an OAuth2 resource serverRS256 lets your service verify signatures using a published public key without ever holding the signing key.

Note: An HS256 secret must be at least 256 bits (32 bytes) of high-entropy data. A short, guessable secret undermines the entire scheme.

Stateless authentication

Traditional session auth stores a session id in a cookie and keeps the matching session in server memory or a shared store. JWTs flip this: the token itself carries the identity, so the server keeps no session state.

1. POST /auth/login (username + password)
2. Server validates credentials, signs a JWT, returns it
3. Client stores the token
4. Each request: Authorization: Bearer <token>
5. Server verifies the signature + exp, builds the SecurityContext, allows the request

The trade-off: a stateless token cannot be revoked simply by deleting a server record — it stays valid until it expires. This is exactly why short lifetimes and refresh tokens exist.

Access tokens vs refresh tokens

To balance security against usability, real systems issue two tokens:

Access tokenRefresh token
LifetimeShort (5–15 min)Long (days/weeks)
Sent onEvery API requestOnly to the refresh endpoint
ContainsUser id + authoritiesMinimal; often opaque
RevocableNo (until expiry)Yes — stored and checked server-side

A short-lived access token limits the damage if it leaks, while the refresh token lets the client get a new access token without re-entering the password. The Refresh Tokens page implements this end to end.

Where to store tokens on the client

This decision is a security trade-off, not a detail:

  • localStorage — easy, but readable by any JavaScript, so it is exposed to XSS attacks.
  • HttpOnly, Secure, SameSite cookie — invisible to JavaScript (mitigates XSS) but requires CSRF protection.
  • In-memory only — safest against XSS for the access token; pair it with a refresh token in an HttpOnly cookie.

Tip: A common production pattern: keep the short-lived access token in memory and the refresh token in an HttpOnly Secure cookie. You get XSS resistance for the long-lived credential and a CSRF surface limited to a single refresh endpoint.

In This Section

Last updated June 13, 2026
Was this helpful?