JWT Decoder & Validator→Specialized Version
🎟️

JWT Header Decoder

Decode header

Decoding happens in this tab. Nothing is sent to a server — but a JWT is a credential, so avoid pasting production tokens into any online tool.

✓Token is within its validity window

Issued: 11/14/2023, 10:13:20 PM

No exp claim — this token never expires on its own.

HEADERAlgorithm & token type

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "2oRQE95wiyElV6g",
  "cty": "JWT"
}

PAYLOADData & claims

{
  "sub": "header-demo",
  "iat": 1700000000
}

SIGNATUREVerification hash

qL8XvNbKtMr3wZjPcYaHdSoUsE2iRgFxTlVnMyDbO9Ac

Claims

ClaimValueMeaning
subregisteredheader-demoSubject — the user or entity it identifies
iatregistered11/14/2023, 10:13:20 PMIssued at

JWT Header Decoder

Decode the JWT header to view the signing algorithm and token type. The header determines how the token signature is verified.

JWT Header Structure

The header is the first part of the JWT (before the first dot) and contains metadata about the token:

``json { "alg": "HS256", "typ": "JWT" } `

Header Fields

FieldDescriptionCommon Values
algSigning algorithmHS256, RS256, ES256
typToken typeJWT
kidKey IDUsed for key rotation
jkuJWK Set URLURL to public keys
x5uX.509 URLURL to certificate
x5cX.509 CertificateCertificate chain

JWT Header Decoder

`javascript function decodeJWTHeader(token) { const headerPart = token.split('.')[0];

// Base64URL decode const base64 = headerPart.replace(/-/g, '+').replace(/_/g, '/'); const padded = base64 + '=='.slice(0, (4 - base64.length % 4) % 4); const decoded = atob(padded);

const header = JSON.parse(decoded);

// Analyze algorithm security const algorithmInfo = getAlgorithmInfo(header.alg);

return { raw: headerPart, decoded: header, algorithm: algorithmInfo }; }

function getAlgorithmInfo(alg) { const algorithms = { 'HS256': { type: 'HMAC', hash: 'SHA-256', keyType: 'symmetric', secure: true }, 'HS384': { type: 'HMAC', hash: 'SHA-384', keyType: 'symmetric', secure: true }, 'HS512': { type: 'HMAC', hash: 'SHA-512', keyType: 'symmetric', secure: true }, 'RS256': { type: 'RSA', hash: 'SHA-256', keyType: 'asymmetric', secure: true }, 'RS384': { type: 'RSA', hash: 'SHA-384', keyType: 'asymmetric', secure: true }, 'RS512': { type: 'RSA', hash: 'SHA-512', keyType: 'asymmetric', secure: true }, 'ES256': { type: 'ECDSA', curve: 'P-256', keyType: 'asymmetric', secure: true }, 'ES384': { type: 'ECDSA', curve: 'P-384', keyType: 'asymmetric', secure: true }, 'ES512': { type: 'ECDSA', curve: 'P-521', keyType: 'asymmetric', secure: true }, 'PS256': { type: 'RSA-PSS', hash: 'SHA-256', keyType: 'asymmetric', secure: true }, 'none': { type: 'None', keyType: 'none', secure: false, warning: 'INSECURE!' } };

return algorithms[alg] || { type: 'Unknown', secure: false }; } `

Algorithm Comparison

AlgorithmTypeBest For
HS256SymmetricSingle server, simple setup
RS256AsymmetricMicroservices, public verification
ES256Elliptic CurveMobile, smaller tokens

The Attacks a Verifier Must Stop

alg: none. A token declaring no algorithm with an empty signature. A library that trusts the header's alg will accept it as valid. Always specify the expected algorithm when verifying rather than reading it from the token.

Algorithm confusion. A token signed with HMAC using the server's *public* RSA key as the secret. If the verifier picks the algorithm from the header, an RS256 verifier can be tricked into running HS256 with a key the attacker already has.

Weak secrets. HS256 with a short or dictionary secret is brute-forceable offline from a single captured token. Use at least 256 bits of real entropy.

No expiry check. exp is a claim, not an enforcement. A library that decodes without verifying, or code that reads claims from a decoded-but-unverified token, accepts expired and forged tokens alike.

`javascript // Specify the algorithm; never trust the header's jwt.verify(token, secret, { algorithms: ['HS256'] }); `

Anyone Can Read the Payload

A JWT is signed, not encrypted. The payload is base64url — readable by anyone holding the token, including the browser it is stored in. Never put anything in it you would not print on a postcard: no passwords, no PII beyond an identifier, no internal keys.

Revocation Is the Hard Part

A signed token is valid until it expires, and there is no way to withdraw one. Options:

ApproachCost
Short expiry (5–15 min) plus refresh tokensStandard; adds a refresh endpoint
A denylist of revoked JTIsReintroduces the state JWTs were meant to avoid
Rotate the signing keyRevokes every token at once
Version claim checked against the user recordA database read per request
If you need immediate revocation for every session, a server-side session is a simpler and more honest choice than a JWT.

Where to Store One

LocationXSS-safeCSRF-safe
localStorageNoYes
sessionStorage`NoYes
Cookie (HttpOnly, Secure, SameSite)YesYes, with SameSite
In-memoryYesYes
An HttpOnly cookie is the safest default. Any token reachable from JavaScript is reachable by any script that gets injected.

Frequently Asked Questions

What does the JWT algorithm (alg) field mean?

The alg field specifies how the token signature is created and verified. HS256 uses a shared secret (HMAC-SHA256)—both parties need the secret. RS256 uses RSA keys (asymmetric)—sign with private key, verify with public key. The algorithm must match between token creation and verification.

Should I use HS256 or RS256?

HS256 is simpler—one secret key for signing and verification. Use when token creator and validator are the same service. RS256 uses public/private keys—sign with private, verify with public. Use when third parties need to verify tokens without accessing signing capability.

What is the kid (Key ID) header?

kid identifies which key was used to sign the token. Essential for key rotation—you can have multiple active keys and specify which one signed each token. Validators look up the correct key using the kid. Without it, you must try all keys or can only use one key at a time.

Related Tools

Explore other tools you might find useful:

More JWT Decoder & Validator tools

You might also need