Back to Research
Fundamentals
JWT
OAuth2
security
API

JWT, explained: claims, signature, and expiry

How a JWT works, what claims such as sub, iss, aud, and exp mean, and what to watch when APIs rely on tokens.

10 min read

JWT (JSON Web Token) became the default format for access tokens and ID tokens in modern APIs. Three base64 parts separated by dots: header, payload, signature. It looks transparent — and that is where many people only call atob() in the browser and believe they authenticated. A JWT is not encryption; it is a signed payload (or an encrypted one, in the case of JWE).

Anatomy of a token

Header:  { "alg": "RS256", "typ": "JWT" }
Payload: { "sub": "user-123", "iss": "https://auth.example.com",
            "aud": "my-api", "exp": 1710003600, "roles": ["ADMIN"] }
Signature: RSASSA-PKCS1-v1_5 over header.payload

Claims you have to validate

  • iss (issuer) — who issued it; it must match your authorization server
  • aud (audience) — which API or client the token was issued for
  • sub (subject) — a stable identifier for the user
  • exp / nbf — expiry and not-before
  • iat — issued at; useful for spotting reused tokens

Signature and JWKS

With RS256, the API fetches public keys from the issuer’s JWKS endpoint, verifies the signature, and only then trusts the payload. Key rotation needs a short-TTL cache and a fallback when kid changes.

When JWT works well

  • Stateless APIs that validate the token locally
  • Microservices that trust the same issuer
  • Short-lived tokens plus a refresh token on the backend

Common mistakes

  • Trusting the payload without validating the signature
  • Accepting HS256 with a weak secret shared across 12 services
  • Ignoring exp, or using infinite clock skew
  • Putting PII or sensitive data in the payload (a JWT is not a secret)
  • An access token that lasts for days “so the session does not expire”
  • Not revoking the refresh token when the user changes the password

How Gatekeeper ID helps

The Spring Boot SDK validates the JWT via the tenant’s JWKS, extracts roles and permissions, and applies RBAC before the controller. You do not reimplement the parser, clock skew, or key rotation — you configure application.yml and protect endpoints.

Protocol context: OAuth2 vs OpenID Connect.

Conclusion

A JWT is a contract between issuer and resource server. Treat validation as critical security code — or use a maintained library or SDK that already implements RFC 7519 correctly.

Related articles