JWT Decoder

Decode and inspect JWT tokens instantly. View header, payload claims, and expiry — no server needed.

Developer ToolsFreeNo Signup
JWT Decoder
Free Tool

How to use JWT Decoder

**What Is a JWT (JSON Web Token)?** A JSON Web Token, defined in RFC 7519, is a compact, URL-safe means of representing claims between two parties. JWTs are the backbone of modern authentication systems used by Auth0, AWS Cognito, Firebase Auth, Okta, and virtually every OAuth 2.0 or OpenID Connect provider in production today. If you've ever logged into a single-page app, called a REST API with a Bearer token, or integrated with a third-party identity provider, you've almost certainly used a JWT without realizing it. Understanding JWTs is not optional for web developers in 2024. Misconfigured or misunderstood JWTs are one of the most common sources of authentication vulnerabilities in production applications. This tool lets you decode and inspect any JWT token instantly, entirely in your browser — co token ever leaves your machine. **The Three-Part Structure of a JWT** Every JWT consists of exactly three Base64URL-encoded sections separated by dots (periods): ``` eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ``` - **Header** (first segment): Metadata about the token — specifically the signing algorithm (`alg`) and token type (`typ`). Example decoded: `("alg": "HS256", "typ": "JWT"}`. Common algorithms are HS256 (HMAC-SHA256), RS256 (RSA-SHA256), and ES256 (ECDSA-SHA256). - **Payload** (second segment): The actual claims — structured data about the user or session. Example decoded: `{"sub": "1234567890", "name": "John Doe", "iat": 1516239022, "exp": 1516242622}`. The `sub` field is the subject (user ID), `iat` is issued-at timestamp, `exp` is expiration timestamp. - **Signature** (third segment): A cryptographic signature generated using the header algorithm and a secret key. This signature is what prevents tampering — if any bit in the header or payload changes, the signature becomes invalid. **How to Use This JWT Decoder** 1. **Obtain your JWT** — Copy a JWT from your browser's developer tools (Application → Cookies or LocalStorage), from an API response, from an Authorization header in a network request (`Bearer eyJ...`), or from a JWT issuance endpoint in your test environment. 2. **Paste the token** — Paste the full JWT string into the input field. The tool automatically detects the three-part dot-separated structure. 3. **Read the decoded output** — The tool instantly displays the decoded header and payload as formatted, readable JSON. All standard registered claims (`iss`, `sub`, `aud`, `exp`, `nbf`, `iat`, `jti`) are highlighted with human-readable timestamp conversions. 4. **Check expiration** — The `exp` claim is shown as both a Unix timestamp and a human-readable date/time. A token with `"exp": 1516242622` expired on January 18, 2018 at 01:30:22 UTC. This tool shows you exactly how much time remains — or how long ago the token expired. 5. **Inspect claims** — Examine custom claims your identity provider injects: roles, permissions, tenant IDs, feature flags, or any application-specific data your backend embeds at issuance time. **Standard JWT Claims Reference** RFC 7519 defines seven registered claim names, each with a specific purpose: | Claim | Full Name | Type | Description | |---|---|---|---| | `iss` | Issuer | String/URI | Entity that issued the token (e.g., `https://myapp.us.auth0.com/`) | | `sub` | Subject | String | Principal the token is about — usually a user ID | | `aud` | Audience | String/Array | Recipient(s) the token is intended for — must match your API's identifier | | `exp` | Expiration Time | Unix timestamp | Token is invalid after this time — verify server-side | | `nbf` | Not Before | Unix timestamp | Token is invalid BEFORE this time — useful for future-dated tokens | | `iat` | Issued At | Unix timestamp | When the token was issued — used to calculate token age | | `jti` | JWT ID | String | Unique identifier — used to prevent token replay attacks | The `nbf` claim is often overlooked. If your server issues a token with `"nbf": 1700000000`, any request made before that Unix timestamp should be rejected — even if the signature is valid. This is useful for scheduling token activation (e.g., grant access at a precise time without distributing the token at that moment). **Real-World Decoded JWT Example** Here is what a real Auth0-style JWT looks like after decoding: Header: ```json { "alg": "RS256", "typ": "JWT", "kid": "abc123def456" } ``` Payload: ```json { "sub": "auth0|5f8a2b3c4d5e6f7a8b9c0d1e", "name": "Jane Smith", "email": "jane@example.com", "https://myapp.com/roles": ["admin", "editor"], "iat": 1698765432, "exp": 1698851832, "nbf": 1698765432, "iss": "https://myapp.us.auth0.com/", "aud": "https://api.myapp.com" } ``` In this token: the user was issued the token on October 31, 2023 and it expires 24 hours later. The `iss` (issuer) is the Auth0 tenant, the `aud` (audience) is the target API, and a custom namespace claim carries the user's roles. **Choosing the Right Signing Algorithm: HS256 vs RS256 vs ES256** The algorithm listed in the JWT header determines how the signature is created and verified. Choosing the wrong one is a security decision with real consequences: **HS256 (HMAC-SHA256) — Symmetric:** - Both the signer and verifier use the same secret key - Simple to set up — one key to manage - Risk: every service that verifies the token must hold the secret — if any service is compromised, all tokens can be forged - Best for: monolithic apps or microservices that are fully trusted and internal-only **RS256 (RSA-SHA256) — Asymmetric:** - The issuer signs with a private key; verifiers use the corresponding public key - The private key stays with your auth server; public key is published at `/.well-known/jwks.json` - Any service can verify tokens without having signing capability — a compromised downstream service cannot forge tokens - Best for: APIs consumed by third parties, multi-tenant systems, and any architecture where you don't fully control all verifying services - Used by: Auth0 (default), AWS Cognito (default), Azure AD **ES256 (ECDSA-SHA256) — Asymmetric:** - Like RS256 but uses elliptic curve cryptography — shorter keys, smaller JWTs, faster verification - A 256-bit EC key provides the same security as a 3072-bit RSA key - Best for: mobile apps and IoT devices where JWT size and CPU cycles matter **Recommendation**: Use RS256 for production APIs. The public/private key separation is a meaningful security boundary. HS256 is acceptable only for internal services where the auth server and all verifiers are within a single trust boundary. **Critical Security Warning: JWTs Are NOT Encrypted** This is the most dangerous misconception in JWT usage. The header and payload are Base64URL-encoded — which means they are trivially decodable by anyone who possesses the token. They are NOT encrypted. Any person or system that intercepts a JWT can read every claim in it. Never place sensitive information in a JWT payload: - ❌ Passwords or password hashes - ❌ Credit card numbers or financial data - ❌ Social Security Numbers or PII beyond what's necessary - ❌ API keys or secrets - ❌ HIPAA-protected health information The signature proves the token was issued by a trusted party and has not been tampered with — it does not protect the payload's confidentiality. If you need confidentiality, use JWE (JSON Web Encryption) per RFC 7516, or encrypt sensitive fields separately before including them as claims. **JWT vs Session Cookies vs OAuth Tokens: Comparison** | Feature | JWT | Session Cookie | Opaque OAuth Token | |---|---|---|---| | Stateless | Yes — self-contained | No — server stores session | No — server stores token | | Payload readable | Yes — Base64URL | No — opaque ID | No — opaque string | | Verification | Signature check | DB/cache lookup | Introspection endpoint | | Revocation | Difficult (until expiry) | Immediate | Immediate | | Size | 200–2000 bytes | ~16–64 bytes | ~32–64 bytes | | Cross-domain | Easy (Authorization header) | Requires CORS config | Easy (Authorization header) | | Best for | Stateless APIs, microservices | Traditional web apps | API authorization with central control | JWTs shine in microservice architectures where each service can verify tokens independently without a central session store — reducing latency and eliminating a single point of failure. They add complexity for web apps that need immediate revocation (e.g., forced logout after password change). **JWT Decoder Libraries for Your Stack** This online decoder is for debugging. In production code, use a battle-tested library: - **JavaScript / Node.js**: `jsonwebtoken` (signing + verifying) or `jwt-decode` (client-side decoding only, no verification) — `npm install jsonwebtoken` - **Python**: `PyJWT` — `pip install PyJWT`. Use `jwt.decode(token, key, algorithms=["RS256"])` — always specify algorithms explicitly - **Java / Spring Boot**: `jjwt` (io.jsonwebtoken) or `java-jwt` (com.auth0). Spring Security ships with built-in JWT support via `spring-security-oauth2-resource-server` - **Go**: `golang-jwt/jwt` — the community-maintained fork of dgrijalva/jwt-go after it was abandoned - **Ruby**: `ruby-jwt` gem - **PHP**: `firebase/php-jwt` Never write your own JWT parser or verifier from scratch. Subtle Base64URL decoding edge cases and algorithm confusion attacks are well-documented — use a library with an active security track record. **Common Mistakes Developers Make with JWTs** **1. Storing JWTs in localStorage (XSS risk)** LocalStorage is accessible to any JavaScript running on your page. An XSS attack can steal every JWT stored there. Store JWTs in HttpOnly cookies when possible — JavaScript cannot read HttpOnly cookies, making XSS token theft impossible. For SPAs that must use localStorage, implement short token expiry (15 minutes) with refresh token rotation. **2. Not validating the `alg` field** The original JWT spec allowed `"alg": "none"`, meaning no signature. Never accept unsigned tokens in production. Explicitly specify which algorithms your application accepts. Libraries like `jsonwebtoken` (Node.js) allow: `jwt.verify(token, secret, { algorithms: ['HS256'] })`. **3. Setting excessively long expiry times** A JWT with `"exp": 9999999999` (year 2286) is effectively a permanent credential. If it's stolen, the attacker has indefinite access. Follow the principle of least privilege: access tokens should expire in 15–60 minutes; refresh tokens in 7–30 days with rotation. **4. Skipping issuer and audience validation** Decoding a token and checking the `exp` is not enough. Always validate `iss` (issuer) against your expected auth server URL and `aud` (audience) against your API's identifier. A token signed by a different tenant's Auth0 account passes signature verification if you use the wrong JWKS endpoint — but `iss` and `aud` validation catches it. **5. Trusting the payload without verifying the signature** Decoding a JWT (which this tool does) is not the same as validating it. Never trust a decoded JWT payload in your application code without first verifying the signature against your public key or secret. Decoding only tells you what the token claims — verification tells you whether those claims are trustworthy. **Pro Tips for JWT Debugging** - **Use this decoder during development** to verify your identity provider is embedding the correct claims. Check that roles, permissions, and tenant IDs are present before writing code that depends on them. - **Compare `iat` and `exp`** to understand your token's validity window. `exp - iat` gives the token lifetime in seconds. A window of 86400 seconds = 24 hours; 3600 seconds = 1 hour. - **The `kid` (Key ID) header claim** tells you which key from a JWKS (JSON Web Key Set) endpoint was used to sign the token. When debugging 401 errors from RS256-signed tokens, verify the `kid` matches a key at your provider's `/.well-known/jwks.json` endpoint. - **Firebase Auth JWTs** always have `"iss"` starting with `https://securetoken.google.com/` and `"aud"` matching your Firebase project ID. If those don't match, the token is from a different project. - **AWS Cognito JWTs** have `"iss"` in the format `https://cognito-idp.{region}.amazonaws.com/{userPoolId}`. Cognito issues separate access and ID tokens — check the `token_use` claim (`"access"` or `"id"`) to ensure you're using the right one for your purpose. **Privacy and Security of This Tool** This JWT decoder runs entirely in your browser using JavaScript. Your token is decoded locally — no network request is made, no data is transmitted, no token is logged or stored. This is the safe way to inspect JWTs containing real user data. Close the tab when you are done and the decoded data is gone.

Frequently Asked Questions

Recommended

Related Tools