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.

Security

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.

Try It — JWT Decoder

Open full tool