All tools

JWK/JWKS Inspector & JWT Signature Debugger

Inspect JWKS keys, match JWTs by kid, verify signatures locally with Web Crypto, and diagnose exactly why token validation fails.

Your tokens and keys stay private. JWT parsing and cryptographic signature verification happen locally in your browser using the Web Crypto API — no tokens, keys, or secrets are sent to CodeAva servers. JWKS URL fetches use a lightweight server-side fetch layer for CORS reliability, but the JWT itself never leaves your browser.

JWT (signed token)
JWKS / JWK

JWT parsing and cryptographic signature verification run entirely in your browser using the Web Crypto API. No tokens, JWKS payloads, or secrets are sent to CodeAva servers. JWKS URL fetches use a lightweight server-side fetch layer for CORS reliability — the JWT itself is never transmitted.

Overview

A JSON Web Key (JWK) is a JSON representation of a cryptographic key. A JSON Web Key Set (JWKS) is a collection of JWKs, typically published at a well-known URL by identity providers like Auth0, Okta, Google, AWS Cognito, and Firebase. When a service issues JWTs signed with an asymmetric algorithm like RS256 or ES256, it uses a private key to sign the token and publishes the matching public key in its JWKS so that consuming applications can verify the signature without access to the private key.

Verifying a JWT against a JWKS requires more than just fetching the keys. The token header carries a kid (key ID) claim that identifies which specific key in the set was used for signing. The verifier must find the key with the matching kid, confirm the algorithm is compatible, and then perform the cryptographic signature check. When this fails — and it commonly does during key rotation, environment mismatches, or configuration errors — the error messages from libraries are often minimal and hard to debug without visibility into the key material and token header.

This tool provides that visibility. Paste or fetch a JWKS and a JWT, and it shows exactly which key was selected, whether the signature is valid, and — if not — a clear diagnosis of why: missing kid, algorithm mismatch, expired token, audience mismatch, wrong environment, or a genuinely invalid signature. All cryptographic operations use the browser's native Web Crypto API — nothing is sent to a server.

Use cases

When to use it

  • Debugging Auth0, Okta, Cognito, or Firebase token failurespaste the JWT from the failing request and the JWKS from your identity provider to verify the signature and inspect claim values in one view.
  • Diagnosing kid rotation issueswhen an identity provider rotates keys, tokens signed with the old key will fail if the new JWKS no longer includes it. The tool shows exactly which kid was in the token and which kids are in the JWKS.
  • Distinguishing cryptographic failures from claim failuresa signature can be valid while the token is still unusable because it is expired, has the wrong audience, or came from the wrong issuer. This tool shows both categories separately.
  • Converting keys between PEM and JWKuse the PEM ↔ JWK converter to translate a PEM public key from a certificate or config file into a JWK for use in a JWKS, or convert a JWK back to PEM for a library that expects PEM format.
  • Testing with the wrong environment's JWKSa common mistake is using a production JWKS to verify a staging token or vice versa. The kid mismatch diagnostic surfaces this immediately.

When it's not enough

  • Encrypted JWTs (JWE)this tool handles signed JWS tokens (3-part). Encrypted JWTs (5-part JWE) require private key decryption and are out of scope for v1. Use a server-side JOSE library to decrypt JWEs.
  • Authorization decisions in productionthis is a debugging tool. Never use it to authorize access — always verify tokens server-side with a trusted library in your application's runtime.
  • Algorithms not yet supportedcurrent support: RS256/384/512, ES256/384/512, HS256/384/512. EdDSA (Ed25519/Ed448) and PS256/384/512 (RSASSA-PSS) are not supported in v1.

How to use it

  1. 1

    Load your JWKS or JWK

    Choose Paste to paste a JWKS JSON or single JWK, JWKS URL to fetch a live endpoint, or OIDC Issuer to auto-discover the jwks_uri from the OpenID Connect discovery document. The server-side fetch handles CORS so the request always works regardless of the provider's CORS policy.

  2. 2

    Paste your JWT

    Paste the signed JWT token (3 dot-separated parts) and click Parse JWT. The header and payload are decoded locally in your browser. The token is never sent to any server.

  3. 3

    Optionally set expected values

    Enter expected issuer (iss), expected audience (aud), or expected algorithm to get richer diagnostics. For HMAC tokens (HS256/HS384/HS512), enter the shared secret.

  4. 4

    Click Verify Signature

    The tool matches the kid from the JWT header to the JWKS, checks algorithm compatibility, and runs the signature verification using the Web Crypto API.

  5. 5

    Review diagnostics and claims

    The Verification tab shows the cryptographic result and diagnostic messages. The Claims tab shows all payload claims with exp/nbf/iss/aud validation results if expected values were provided.

Common errors and fixes

kid not found in JWKS

The JWT was signed with a key that is no longer in the JWKS. Common causes: key rotation (the old key was removed before all tokens expired), wrong environment JWKS (staging vs production), or the JWKS URL is cached and stale. Refetch the JWKS and check whether the kid in the JWT header matches any key in the set.

Algorithm mismatch between JWT and key

The alg in the JWT header does not match the alg declared in the matched key. Verify that the identity provider configuration and the application's expected algorithm are in sync. RS256 and ES256 are not interchangeable — they use different key types (RSA vs EC).

Signature invalid

The signature did not verify against the selected key. Possible causes: the token was tampered with, you are using the wrong key or JWKS, the JWT was signed by a different service, or the algorithm parameters do not match. Check that the JWKS URL matches the issuer in the JWT's iss claim.

Token is expired

The exp claim is in the past. For debugging purposes, this is expected if you are testing with an old token. In production, ensure your token refresh logic works before tokens expire. Check clock drift if tokens expire immediately after being issued.

Audience mismatch

The aud claim in the token does not match the audience you expect. Make sure the token was requested with the correct audience parameter for your application. Different Auth0/Okta APIs often issue tokens with different audience values.

5-part token detected (JWE)

This token is an encrypted JWT, not a signed JWT. Encrypted JWTs require the private key to decrypt. Use a server-side library like jose (Node.js) or your platform's equivalent to decrypt and inspect a JWE.

PEM to JWK conversion fails

Ensure the PEM is complete and unmodified, including the BEGIN/END header lines. PKCS#1 RSA keys (BEGIN RSA PUBLIC KEY) may need to be converted to SPKI format (BEGIN PUBLIC KEY) first using openssl rsa -pubout. EC keys must use a supported curve (P-256, P-384, P-521).

Frequently asked questions

What is a JWKS and why is it used for JWT verification?

A JWKS (JSON Web Key Set) is a JSON document containing a collection of public keys. It is the standard mechanism identity providers use to publish the keys that applications should use to verify JWT signatures. The JWKS is typically hosted at a well-known URL — for example https://your-issuer.com/.well-known/jwks.json — and can be discovered automatically through the OIDC discovery document at /.well-known/openid-configuration.

In an asymmetric JWT flow (RS256, ES256, etc.), the identity provider signs the token with a private key that it holds exclusively. The matching public key is published in the JWKS. A verifying application reads the kid from the JWT header, finds the key with the matching kid in the JWKS, and uses it to verify the signature. No secret needs to be shared — the private key never leaves the identity provider.

Identity providers rotate JWKS keys periodically. Applications should cache the JWKS with a reasonable TTL and re-fetch it on kid cache-miss rather than on every request. If a token arrives with a kid that is not in the cached JWKS, the application should fetch the JWKS once more before failing — the key may have been rotated and the cache may be stale.

JWT signature verification troubleshooting guide

SymptomLikely causePractical fix
kid not foundKey rotation, wrong environment JWKS, or stale JWKS cacheRe-fetch JWKS. Confirm the issuer URL matches the token's iss claim. Check staging vs production endpoints.
alg mismatchToken uses RS256 but JWKS key declares ES256, or vice versaAlign the algorithm in the identity provider config and the verifier's expected algorithm. RS256 and ES256 use different key types.
Signature invalidWrong JWKS, tampered token, or wrong key selectedVerify the JWKS URL matches the issuer. Check that the correct key is selected. Confirm the token has not been modified.
Token expiredexp claim is in the pastUse a fresh token. For debugging, check clock drift. In production, verify token refresh logic runs before expiry.
Token not yet validnbf claim is in the futureCheck system clock. nbf is sometimes set a few seconds ahead to account for clock skew between services.
Audience mismatchToken aud does not match the expected audience for this APIRequest the token with the correct audience parameter. Different APIs on the same IdP often have different audience values.
Issuer mismatchToken iss does not match what the application expectsConfirm the application is configured with the right issuer URL. Staging and production environments often have different issuer values.
Wrong environment keyProduction token verified against staging JWKS or vice versaUse the JWKS URL from the same environment as the issuer in the token's iss claim.

Node.js JWT verification with JWKS

The jose library is the recommended modern approach for JWKS-backed JWT verification in Node.js. It handles JWKS fetching, caching, and kid matching automatically.

import { createRemoteJWKSet, jwtVerify } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://your-issuer.com/.well-known/jwks.json")
);

// Call this per incoming request — jose caches the JWKS internally.
const { payload, protectedHeader } = await jwtVerify(token, JWKS, {
  issuer: "https://your-issuer.com",
  audience: "https://your-api.com",
});

// payload is the verified claims object.
// Never trust payload before this call returns successfully.

JWKS caching note: jose's createRemoteJWKSet caches the fetched keys in memory and re-fetches on kid cache-miss. For high-volume services, consider a shared cache layer so that key-rotation fetches do not spike per-instance. Never disable caching entirely — re-fetching the JWKS on every request is a denial-of-service risk against your identity provider.