Reading — step 1 of 5
Learn
Keys From the Token Itself: jku, jwk, x5u, x5c
The registry you just built answers one question: which of my keys is this?
kid is a name, resolved against a key set you fetched from an issuer you chose.
Four other header parameters answer a different question — which key should I
use? — and let the token answer it.
Four parameters, one idea
The JWS specification (RFC 7515) defines these alongside kid:
| Parameter | Header carries | A trusting verifier |
|---|---|---|
jwk | a public key, inline | verifies with it |
jku | a URL of a JWK Set | fetches the set, uses a key from it |
x5c | a certificate chain, inline | takes the key from the leaf |
x5u | a URL of a certificate chain | fetches it, then as above |
kid is a name; these four are the key itself, or a pointer to it. That is
the difference between a lookup and an instruction.
Why this can never be made secure
RFC 7519 §11.1 settles it: a JWT's contents cannot be relied on for a trust
decision unless they are cryptographically secured and the signing key is
verifiably under the control of the party named as the issuer. A key that arrived
inside the token is under the control of whoever wrote the token. An attacker
facing a verifier that honours jwk therefore needs no secret and no weakness in
HMAC or RSA: they generate a key pair, put the public half in the header, sign
with the private half, and the check passes — proving only that the sender can
sign with their own key.
Where algorithm confusion had the token choosing what to do with your key, this is the token choosing which key — the same failure one level up.
The two URL forms cost you a request as well. You must fetch the key before any signature is verified, so an unauthenticated stranger picks a URL your backend retrieves: an internal admin page, a cloud metadata endpoint, one host of a private range at a time. Rejecting the key afterwards does not un-send that.
Defenses that only look like defenses
- Allowlisting the
jkuhost. One open redirect there, or one endpoint that echoes attacker JSON back, and the allowlist is satisfied. - Accepting
jwkwhen you recognise its thumbprint. That iskidwith a key parser bolted on: same lookup, more attack surface, no new capability. - Validating the
x5cchain. Against which root? If it is a CA you operate, you have just described a key store you control — so use the store.
The clause behind the rule
Resolve keys by name, from a store you control. RFC 7519 §7.2 lets you be blunt:
step 5 requires the JOSE header to hold only parameters whose syntax and semantics
your implementation understands and supports, bar any the spec marks ignorable
when not understood, and a failed step means the JWT MUST be rejected. typ is
the one this spec says implementations ignore (§5.1). A jku you do not implement
gets no such exemption from you: treat it as invalid input, not as a hint.
Common mistakes
- Falling back to the header key when no other key matches. The unknown-
kidpath is where this gets written, and it turns a miss into a bypass. - Denylisting header parameters instead of allowlisting them. New ones get registered; your list of four does not grow by itself.
- Fetching first and judging afterwards. The request has already left.
- Allowing
jkubecause it points at your own JWKS host. It still moves the choice of key into the token.
Your exercise
You will accept kid lookups against a trusted registry and reject any token
whose header carries key material or a key URL.
The visible test punishes scanning for the wrong thing. Its third token carries
kid: k1 and a signature that is a correct HMAC under k1, so everything about
it verifies. It also carries a jku, so the answer is REJECTED header_key=jku.
Scan for the four before alg and before the registry, or you report OK kid=k1
on a token that asked you to fetch a key from keys.attacker.test.
With several of the four present, report the first in the fixed order jwk,
jku, x5c, x5u, not whichever came first in the JSON. And a token with no
kid is REJECTED unknown_kid: it is well formed, you simply hold no key for it,
and trying your other keys is the very fallback this lesson is about.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…