flashman
← All posts

OAuth JWT bearer assertion debugging

Debug OAuth JWT bearer assertions by tracing issuer, audience, time claims, signing-key rotation, client identity, and the token endpoint that rejects them.

2026-09-29 · 6 min read · Rahul Chitturi

  • oauth
  • jwt
  • security

The OAuth JWT bearer grant and private-key JWT client authentication both send a signed JWT to the token endpoint. The authorization server expects a short-lived assertion whose issuer, subject, audience, and signature match a registered client.

A 400 or 401 here is often a claim mismatch rather than a bad client secret. The same key can sign a token that is valid as an access token and useless as a client assertion because the audience is different.

Separate the assertion from the access token

Record the grant type or client authentication method, the token endpoint URL, the assertion header and payload, the registered client ID, and the key identifier the server selected. Do not log the private key or a production assertion that can still be replayed.

  • Confirm iss and sub match the registered client.
  • Set aud to the exact token endpoint the server expects.
  • Keep exp short and check iat and nbf against server time.
  • Use a unique jti when the server stores replay protection.

Check signature selection and clock skew

kid, algorithm, and the registered public key must agree. A rotation that publishes a new key but leaves the client signing with the old one fails closed. Servers also reject assertions that expired before they arrived, so compare client and authorization-server clocks before widening the lifetime.

Some servers require the audience to be the issuer identifier, others require the full token-endpoint URL. Read the server's metadata and client-auth docs instead of copying an access-token aud claim into the assertion.

Reproduce with a synthetic assertion

Use Flashman's JWT decoder on a short-lived test assertion, the timestamp converter for iat and exp, the JSON formatter for the token error body, and the URL parser to compare the audience with the real token endpoint.

Test wrong audience, expired and not-yet-valid assertions, reused jti values, algorithm mismatches, key rotation overlap, issuer and subject swaps, and both client authentication and the JWT bearer grant if you use both.

Try these tools