How JWT Signature Verification Works
Learn the step-by-step process of JWT signature verification, how signing algorithms protect token integrity, and what happens when verification fails.
Detailed Explanation
Signature verification is the process that makes JWTs trustworthy. Without it, anyone could craft a token with arbitrary claims. The signature mathematically proves that the token was created by a trusted issuer and has not been modified since signing.
The verification process step by step:
Input: eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIn0.signature_bytes
Step 1: Split the token into three parts at the period delimiters
header_b64 = "eyJhbGciOiJSUzI1NiJ9"
payload_b64 = "eyJzdWIiOiJ1c2VyMTIzIn0"
signature = "signature_bytes"
Step 2: Decode the header to determine the algorithm
header = { "alg": "RS256" }
Step 3: Check that the algorithm is in your allowlist
Allowed: ["RS256"] → OK
Step 4: Select the correct verification key
For RS256: Use the issuer's public key (from JWKS)
For HS256: Use the shared secret
Step 5: Recompute the expected signature
signing_input = header_b64 + "." + payload_b64
expected = RSA_VERIFY(SHA256(signing_input), publicKey)
Step 6: Compare the received signature to the expected value
If match → token is authentic and unmodified
If no match → token is rejected
Integrity guarantee:
The signature covers both the header and the payload. If an attacker modifies any byte in either section (for example, changing "role":"user" to "role":"admin"), the signature becomes invalid. The verification step detects this tampering and rejects the token. This is why the header and payload are included in the signing input, not just the payload.
Key selection with kid:
When the issuer maintains multiple signing keys (common during key rotation), the JWT header includes a kid (key ID) field. The verifier uses kid to select the matching key from the JWKS endpoint. If no key matches the kid, verification fails. This mechanism enables seamless key rotation without downtime.
Timing-safe comparison:
The final comparison between the computed and received signature must use a constant-time comparison function to prevent timing attacks. If the comparison short-circuits on the first different byte, an attacker can determine the correct signature one byte at a time by measuring response times. All reputable JWT libraries use timing-safe comparison internally, but custom implementations must be careful about this.
What verification does NOT guarantee:
Signature verification proves authenticity and integrity, but it does not prove that the token is valid for use right now. You must still check exp, nbf, iss, and aud claims separately. A correctly signed but expired token will pass signature verification but should be rejected by the claims validation step.
Use Case
An API gateway performs signature verification on every incoming JWT, fetching the issuer's JWKS public keys and caching them to validate tokens without contacting the auth server.