How to Decode a JWT Token: Complete Tutorial (2026)
1. What Is a JWT and Why You Need to Decode It
A JSON Web Token (JWT) is a compact, URL‑safe means of representing claims between two parties. It consists of three Base64URL‑encoded parts: a header that describes the token type and signing algorithm, a payload that carries the claims, and a signature that guarantees integrity. Decoding a JWT lets developers inspect the claims, verify expiration, and confirm that the token was signed with the expected secret or public key. In modern APIs, single‑page applications, and micro‑services, JWTs replace session cookies, so understanding their structure is essential for debugging authentication flows, troubleshooting authorization errors, and ensuring security compliance.
Because JWTs travel over the wire in plain text, any misconfiguration—such as using a weak signing secret or forgetting to set an exp claim—can expose your application to replay attacks or token forgery. By decoding the token with a trusted client‑side tool like the WebDevWorker JWT Decoder, you keep the token inside the browser, guaranteeing that sensitive data never leaves the user’s device. This guide walks you through the anatomy, a quick workflow, code examples in five languages, and a security checklist to keep your implementation robust.
2. JWT Anatomy: The Header.Payload.Signature Formula
The JWT format follows the header.payload.signature pattern, where each segment is Base64URL‑encoded. Below is a real‑world example token (line‑breaks added for readability):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpv
aG4gRG9lIiwiaWF0IjoxNjkxMjM0NTY3LCJleHAi
OjE2OTEyNzA1Njd9
.
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Header (first part) – declares the token type (JWT) and the signing algorithm (HS256). Decoded JSON:
{
"alg": "HS256",
"typ": "JWT"
}
Payload (second part) – contains the claims. Decoded JSON:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1691234567,
"exp": 1691270567
}
Signature (third part) – HMAC‑SHA256 of base64url(header) + "." + base64url(payload) signed with the secret key. The signature ensures that any alteration to the header or payload invalidates the token.
Standard registered claim names are listed in the table below. Understanding each claim helps you decide which ones to validate in your application.
| Claim | Description |
|---|---|
iss | Issuer – identifies the principal that issued the JWT. |
sub | Subject – identifies the principal that is the subject of the JWT. |
aud | Audience – intended recipients; verification ensures the token is for your service. |
exp | Expiration Time – Unix timestamp after which the token MUST NOT be accepted. |
nbf | Not Before – Unix timestamp before which the token MUST NOT be accepted. |
iat | Issued At – Unix timestamp when the token was issued. |
jti | JWT ID – unique identifier for the token, useful for replay detection. |
Remember that the header and payload are merely Base64URL strings; you can decode them with any Base64 decoder. For time‑based claims like exp or iat, the timestamp converter is handy.
3. Step-by-Step: Decode Any JWT in 30 Seconds
- Open the tool – Navigate to the WebDevWorker JWT Decoder. The interface runs 100% client‑side, so your token never leaves the browser.
- Paste the token – Copy the entire JWT string (including the two dots) into the input box.
- Read the header – The decoder instantly shows the decoded JSON header. Verify the
algmatches your expected algorithm (e.g.,HS256orRS256). - Inspect the payload – Claims appear in a formatted view. Look for
exp,nbf, andiat. Use the linked timestamp converter if you need human‑readable dates. - Check expiration – If
expis present, compare it to the current time. The tool highlights expired tokens in red. - Verify the signature – Enter the secret key (for HMAC) or the public key (for RSA/ECDSA) in the verification field. The decoder recalculates the signature using the HMAC utility and confirms a match.
- Review warnings – The UI flags common misconfigurations such as missing
exp, use ofalg=none, or weak key lengths.
Following these steps ensures you quickly validate both the integrity and the temporal validity of any JWT without writing a single line of code.
4. Decode and Verify JWTs in Code: 5 Languages
Below are ready‑to‑copy snippets that decode a JWT and verify its signature. Replace YOUR_TOKEN and YOUR_SECRET (or public key) with your actual values.
JavaScript (Node.js) – jsonwebtoken
const jwt = require('jsonwebtoken');
const token = 'YOUR_TOKEN';
const secret = 'YOUR_SECRET';
try {
const decoded = jwt.verify(token, secret, { algorithms: ['HS256'] });
console.log('Header:', decoded.header);
console.log('Payload:', decoded);
} catch (err) {
console.error('Invalid token:', err.message);
}
Python – PyJWT
import jwt
token = 'YOUR_TOKEN'
secret = 'YOUR_SECRET'
try:
decoded = jwt.decode(token, secret, algorithms=['HS256'])
print('Payload:', decoded)
except jwt.ExpiredSignatureError:
print('Token has expired')
except jwt.InvalidTokenError as e:
print('Invalid token:', e)
Go – golang-jwt
package main
import (
"fmt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
tokenString := "YOUR_TOKEN"
secret := []byte("YOUR_SECRET")
token, err := jwt.Parse(tokenString, func(t *jwt.Token) (interface{}, error) {
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method")
}
return secret, nil
})
if err != nil || !token.Valid {
fmt.Println("Invalid token:", err)
return
}
fmt.Printf("Claims: %+v\n", token.Claims)
}
Rust – jsonwebtoken crate
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
exp: usize,
// add other fields as needed
}
fn main() {
let token = "YOUR_TOKEN";
let secret = "YOUR_SECRET";
let validation = Validation::new(Algorithm::HS256);
match decode::(token, &DecodingKey::from_secret(secret.as_ref()), &validation) {
Ok(data) => println!("Claims: {:?}", data.claims),
Err(err) => eprintln!("Invalid token: {}", err),
}
}
cURL (verify signature with HMAC) & PHP
# cURL – using OpenSSL to verify HMAC (requires base64url conversion)
TOKEN="YOUR_TOKEN"
SECRET="YOUR_SECRET"
HEADER=$(echo "$TOKEN" | cut -d. -f1)
PAYLOAD=$(echo "$TOKEN" | cut -d. -f2)
SIGNATURE=$(echo "$TOKEN" | cut -d. -f3)
EXPECTED=$(echo -n "$HEADER.$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET" -binary | base64 | tr '+/' '-_' | tr -d '=')
if [ "$EXPECTED" = "$SIGNATURE" ]; then echo "Signature valid"; else echo "Invalid signature"; fi
# PHP example
getMessage();
}
?>
These snippets cover the most common environments. For RSA/ECDSA signatures, swap the HMAC secret for a PEM‑encoded public key and adjust the algorithm name accordingly.
5. Security Checklist: 7 Attacks That Target JWTs
| Attack Vector | How to Prevent |
|---|---|
alg=none misuse | Reject tokens where alg is none unless explicitly allowed. Enforce algorithm whitelist on the server. |
| Weak secret / brute‑force | Use a secret of at least 256 bits for HMAC, rotate regularly, and store it in a secret manager. |
Missing exp claim | Always include an expiration time and reject tokens without it. |
kid injection | Validate the kid against a known list of keys; never fetch keys from untrusted URLs. |
| XSS token theft | Store JWTs in httpOnly cookies or secure storage; never expose them to JavaScript unless necessary. |
| Replay attacks | Implement token revocation lists or short‑lived access tokens combined with refresh tokens. |
| Algorithm downgrade | Hard‑code the expected algorithm on verification; never trust the token‑provided alg value alone. |
By following this checklist you mitigate the most common vulnerabilities. For deeper analysis, refer to the full guide How to Decode a JWT Token: Complete Tutorial (2026).