← Blog
March 20, 2026 · 6 min

The JWT Header Explained

The first segment of a JWT looks tiny, but alg, typ, and kid carry real security weight. Here's exactly what belongs in a JWT header and why.

The three-part anatomy A JWT is three base64url-encoded segments joined by dots: `header.payload.signature`. The header is the smallest part but it tells the verifier **how** to check the token, which makes it security-critical in its own right.

What's actually inside A minimal header is a small JSON object: - `alg`: the signing algorithm, e.g. `HS256`, `RS256`, `ES256`, or `none` (which you should always reject) - `typ`: almost always the literal string `JWT` - `kid`: an optional key identifier, used to select which key to verify against when multiple keys are in rotation

That's usually it. The header is not encrypted — it's base64url-encoded, meaning anyone can decode and read it instantly. Never put secrets in the header.

Why `alg` is dangerous if trusted blindly The single most cited JWT vulnerability class comes from verifiers that read `alg` from the incoming token and dynamically choose how to verify it. An attacker can change `alg` to `none` and strip the signature, or change an RS256 token to claim `HS256` and sign it with the RSA public key (which is, by design, public) as if it were an HMAC secret. A correct verifier **ignores the token's claimed algorithm for key selection** and instead uses a fixed, explicitly configured algorithm (or small allow-list) set by your own server code.

What `kid` is for When you rotate signing keys, you need a way for the verifier to know which public key (or secret) corresponds to a given token without guessing. The `kid` header value is an identifier — often a short hash or version number — that maps to a specific key in your key store or JWKS document. It is safe to trust `kid` as a lookup index because, even if an attacker manipulates it, they can only point the verifier at a key **you already control and trust**, not smuggle in an arbitrary key.

Other header fields you might see - `cty`: content type, rarely used, relevant mostly for nested JWTs - `x5c` / `x5t`: certificate chain or thumbprint, used in some enterprise/X.509-based setups - `crit`: lists header parameters that must be understood and processed — a verifier that doesn't recognize a listed extension should reject the token

Decoding a header yourself Because the header is just base64url JSON, you can inspect it without any library — split the JWT on `.`, take the first segment, base64url-decode it, and parse as JSON. Our decoder tool does exactly this and is a fast way to sanity-check what a library actually produced.

Checklist - Never let the token dictate the verification algorithm — configure it server-side. - Reject `alg: none` unconditionally, including in test/dev environments. - Use `kid` to support multiple valid keys during rotation windows. - Remember the header is readable by anyone — never put secrets in it. - Treat unexpected or unrecognized header fields (especially with `crit`) as a reason to reject the token.