Last updated
Decoding a Basic JWT
A JSON Web Token looks like three base64url-encoded strings separated by dots. Paste a token like this into the decoder:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFsaWNlIEpvaG5zb24iLCJpYXQiOjE3MDAwMDAwMDAsImV4cCI6MTcwMDAwMzYwMH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The decoder splits it into three parts and decodes each one.
Decoded Header
The first segment is the header, which describes the token type and signing algorithm:
{
"alg": "HS256",
"typ": "JWT"
}
- alg: HS256 — HMAC with SHA-256 signing algorithm
- typ: JWT — confirms this is a JSON Web Token
Other common algorithm values include RS256 (RSA), ES256 (ECDSA), and PS256 (RSA-PSS).
Decoded Payload — Standard Claims
The second segment is the payload containing claims about the user and token metadata:
{
"sub": "1234567890",
"name": "Alice Johnson",
"iat": 1700000000,
"exp": 1700003600
}
The decoder converts Unix timestamps to human-readable dates:
- sub: Subject — the user identifier (1234567890)
- iat: Issued At — November 14, 2023 22:13:20 UTC
- exp: Expires At — November 14, 2023 23:13:20 UTC (1 hour later)
- Token status: EXPIRED (shown in red if past expiration)
Decoding an Auth0 Token
Tokens from Auth0 include additional standard and custom claims. Decoded payload example:
{
"iss": "https://your-tenant.auth0.com/",
"sub": "auth0|64a1b2c3d4e5f6a7b8c9d0e1",
"aud": ["https://api.yourapp.com", "https://your-tenant.auth0.com/userinfo"],
"iat": 1700000000,
"exp": 1700086400,
"azp": "your_client_id",
"scope": "openid profile email read:data",
"permissions": ["read:users", "write:posts"]
}
- iss: Issuer — the Auth0 tenant that issued the token
- aud: Audience — the APIs this token is valid for
- azp: Authorized party — the client application
- scope: Granted OAuth scopes
- permissions: Custom RBAC permissions
Decoding a Firebase Token
Firebase Authentication tokens include Firebase-specific claims:
{
"iss": "https://securetoken.google.com/your-project-id",
"aud": "your-project-id",
"auth_time": 1700000000,
"user_id": "abc123xyz",
"sub": "abc123xyz",
"iat": 1700000000,
"exp": 1700003600,
"email": "user@example.com",
"email_verified": true,
"firebase": {
"identities": {
"email": ["user@example.com"]
},
"sign_in_provider": "password"
}
}
The decoder shows the nested firebase object with sign-in provider information, useful for debugging authentication flows.
Expiration Checking
The decoder automatically checks the exp claim against the current time and displays one of three statuses:
- Valid — token has not expired yet, shows time remaining (e.g., "Expires in 45 minutes")
- Expired — token is past its expiration, shows how long ago it expired (e.g., "Expired 2 hours ago")
- Not Yet Valid — token has an
nbf(not before) claim in the future
This instant expiration check is the fastest way to diagnose 401 Unauthorized errors caused by expired tokens during development.
Identifying the Algorithm
The alg field in the header tells you how the token was signed. Common values and what they mean:
// HMAC (symmetric — same secret for signing and verification)
{ "alg": "HS256" } // HMAC-SHA256
{ "alg": "HS384" } // HMAC-SHA384
{ "alg": "HS512" } // HMAC-SHA512
// RSA (asymmetric — private key signs, public key verifies)
{ "alg": "RS256" } // RSA-SHA256
{ "alg": "RS384" } // RSA-SHA384
// ECDSA (asymmetric — smaller keys than RSA)
{ "alg": "ES256" } // ECDSA-SHA256
{ "alg": "ES384" } // ECDSA-SHA384
If you see "alg": "none", this is a security red flag — it means the token has no signature and should be rejected by any properly configured server.
Decoding an AWS Cognito Token
AWS Cognito tokens include Cognito-specific claims:
{
"sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX",
"client_id": "your_app_client_id",
"origin_jti": "uuid-here",
"token_use": "access",
"scope": "aws.cognito.signin.user.admin",
"auth_time": 1700000000,
"exp": 1700003600,
"iat": 1700000000,
"jti": "another-uuid",
"username": "alice"
}
The token_use claim distinguishes between access tokens and ID tokens in Cognito's dual-token system.
Understanding the Signature Section
The third segment of a JWT is the signature. The decoder displays it as a hex string:
Signature (hex):
49f94ac7044948c78a285d904f87f0a4c7897f7e8f3a4eb2255fda750b2c385
Note: Signature verification requires the secret key (HS256)
or public key (RS256/ES256) used to sign this token.
This decoder shows the signature for inspection only.
Always verify signatures server-side using your auth library.
The decoder does not verify the signature — that requires the secret or public key. Use this tool for inspection and debugging only, never for production token validation.
Debugging a Custom Claims Token
When your application adds custom claims to tokens, decode them to verify they are set correctly:
{
"sub": "user_789",
"iat": 1700000000,
"exp": 1700086400,
"role": "admin",
"tenantId": "tenant_abc123",
"features": ["analytics", "export", "api_access"],
"plan": "enterprise",
"maxApiCalls": 100000
}
Decoding the token after login confirms that the role, tenantId, features, and plan claims are all present with the correct values — much faster than adding debug logging and redeploying.
Security Note — Client-Side Decoding
The JWT Decoder processes tokens entirely in your browser. No token data is sent to any server. This is important because JWT payloads often contain sensitive information:
- User IDs and email addresses
- Roles and permissions
- Tenant and organization identifiers
- Custom application claims
Always verify that any JWT decoder tool you use processes tokens locally. The base64url encoding of a JWT is not encryption — anyone who can read the token can decode the payload. Sensitive data in JWT payloads should be treated with the same care as any other sensitive data.