JWT Decoder & Validator→Specialized Version
🎟️

ID Token Decoder

Decode ID tokens

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

Expires: 3/17/2030, 5:46:40 PM (1294d 22h 29m from now)

HEADERAlgorithm & token type

{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "key-2026-01"
}

PAYLOADData & claims

{
  "iss": "https://accounts.example.com",
  "sub": "10769150350063",
  "aud": "client-42",
  "email": "ada@example.com",
  "email_verified": true,
  "nonce": "n-0s6_WzA2Mj",
  "auth_time": 1700000000,
  "exp": 1900000000
}

SIGNATUREVerification hash

Kv8dLnQpR2xWmYtBcFaTjZoUiE7sNhXrPgVyDlM4OqI

Claims

ClaimValueMeaning
issregisteredhttps://accounts.example.comIssuer — who minted the token
subregistered10769150350063Subject — the user or entity it identifies
audregisteredclient-42Audience — who is allowed to accept it
emailada@example.comUser email
email_verifiedtrueCustom claim
noncen-0s6_WzA2MjCustom claim
auth_time1700000000Custom claim
expregistered3/17/2030, 5:46:40 PMExpiration time

ID Token Decoder

Decode OpenID Connect ID tokens to extract user identity information. ID tokens provide authenticated user details to client applications.

ID Token vs Access Token

FeatureID TokenAccess Token
PurposeUser identityAPI authorization
AudienceClient applicationResource server (API)
ContentUser claims (name, email)Scopes and permissions
FormatAlways JWTJWT or opaque
SenderAlways to clientClient to API

Standard ID Token Claims

ClaimRequiredDescription
issYesIssuer (OAuth server URL)
subYesSubject (unique user ID)
audYesAudience (your client ID)
expYesExpiration time
iatYesIssued at time
auth_timeOptionalWhen user authenticated
nonceConditionalReplay attack prevention
acrOptionalAuthentication context class
amrOptionalAuthentication methods used

ID Token Decoder

``javascript function decodeIDToken(token) { const parts = token.split('.'); if (parts.length !== 3) { throw new Error('ID tokens must be JWTs'); }

const decode = (s) => JSON.parse(atob(s.replace(/-/g, '+').replace(/_/g, '/'))); const header = decode(parts[0]); const payload = decode(parts[1]);

// Standard OIDC claims const standardClaims = { issuer: payload.iss, subject: payload.sub, audience: payload.aud, expiresAt: new Date(payload.exp * 1000), issuedAt: new Date(payload.iat * 1000), authTime: payload.auth_time ? new Date(payload.auth_time * 1000) : null, nonce: payload.nonce };

// User profile claims const profileClaims = { name: payload.name, email: payload.email, emailVerified: payload.email_verified, picture: payload.picture, locale: payload.locale, phone: payload.phone_number };

// Provider-specific claims const customClaims = {}; const knownClaims = ['iss', 'sub', 'aud', 'exp', 'iat', 'auth_time', 'nonce', 'name', 'email', 'email_verified', 'picture', 'locale', 'phone_number'];

for (const [key, value] of Object.entries(payload)) { if (!knownClaims.includes(key)) { customClaims[key] = value; } }

return { header, standardClaims, profileClaims, customClaims, raw: payload }; } `

OIDC Profile Scopes

ScopeClaims Included
openidsub (required for ID token)
profilename, family_name, given_name, picture
emailemail, email_verified
addressaddress (formatted, street, city, etc.)
phonephone_number, phone_number_verified

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 is an ID token used for?

ID tokens are for the client application to learn about the user—display their name, email, profile picture. They prove the user authenticated. Never send ID tokens to APIs (that's what access tokens are for). Use ID tokens locally to personalize the user experience.

What is the nonce claim?

The nonce prevents replay attacks. When starting authentication, generate a random nonce, store it, and include it in the auth request. The ID token will contain the same nonce. Verify they match—if they don't, someone may be replaying an old token.

Should I validate the ID token?

Yes, always. Validate: 1) Signature using provider's public keys (JWKS), 2) iss matches expected issuer, 3) aud contains your client_id, 4) exp hasn't passed, 5) nonce matches what you sent. Libraries like oidc-client handle this automatically.

Related Tools

Explore other tools you might find useful:

More JWT Decoder & Validator tools

You might also need