What Is JWT
JSON Web Token (JWT) is an open standard (RFC 7519) for passing information securely between parties as a compact, URL-safe string. You can send it in an HTTP header, a URL parameter, or a cookie.
Two common use cases:
- Authentication: After login, the server issues a JWT. The client carries it in later requests to prove identity. Unlike sessions, the server does not store session state, so JWT fits distributed and microservice architectures well.
- Information exchange: JWTs carry a signature, so the receiver can verify the content has not been tampered with. This makes them useful for passing trusted data between services, such as OAuth2 access tokens.
The Three-Part Structure
A JWT looks like this, three segments separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The three parts are Header, Payload, and Signature. Each one is Base64URL-encoded JSON.
Part 1: Header
Decoded, it describes the token type and signing algorithm:
{
"alg": "HS256",
"typ": "JWT"
}
alg: the signing algorithm. HS256 means HMAC with SHA-256.typ: the token type, always JWT.
Part 2: Payload
This holds the actual data, known as claims. Decoded:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
Standard claims defined by RFC 7519:
| Field | Meaning | Description |
|-------|---------|-------------|
| iss | Issuer | Who issued the token |
| sub | Subject | Usually the user ID |
| aud | Audience | Who the token is intended for |
| exp | Expiration | Token is invalid after this time |
| iat | Issued at | When the token was issued |
| nbf | Not before | Token is not valid before this time |
You can also add custom claims such as name, role, or email.
Part 3: Signature
This prevents tampering. It is covered next.
How Signature Verification Works
Take HS256, the most common algorithm. Signing works in three steps:
- Concatenate
base64url(header) + "." + base64url(payload)into one string. - Run HMAC-SHA256 over that string using a secret key.
- Base64URL-encode the result to get the signature.
HMACSHA256(
base64url(header) + "." + base64url(payload),
secret
)
When the server receives a token, it repeats the same computation and compares the result to the signature in the token. If they match, the token is authentic. Because an attacker does not know the secret, they cannot produce a valid signature for a modified payload. That is what makes the signature tamper-proof.
One detail worth knowing: Base64URL differs from standard Base64. Base64URL replaces + with - and / with _, and drops the trailing = padding. This keeps the token safe to place in a URL without special characters causing trouble.
Common Security Pitfalls
The alg: none Vulnerability
The Header contains an alg field that tells the server which algorithm to use. Some early libraries trusted this field directly. An attacker could change alg to none, drop the signature, and certain libraries would skip verification entirely.
Defense: Hardcode the list of accepted algorithms on the server (for example, only HS256). Never trust the algorithm declared inside the token.
Weak Keys
HS256 security depends entirely on the key. If it is short or predictable (like "secret" or "123456"), an attacker can brute force it and forge any token.
Recommendation: Use a random key at least 32 bytes long. Never commit it to source control.
Expiration Time
The exp claim controls how long a token stays valid. Set it too long (say, a year) and a leaked token does a lot of damage. Set it too short and users log in constantly.
A common pattern is a 15 to 30 minute access token paired with a 7 to 30 day refresh token for renewal.
Storage: Cookie vs LocalStorage
An old debate, with tradeoffs on both sides:
- LocalStorage: Easy to implement, the frontend can read it freely. The downside is exposure to XSS attacks that steal tokens.
- HttpOnly Cookie: JavaScript cannot read it, which blocks XSS theft. But you need the SameSite attribute to defend against CSRF.
For security-sensitive systems, prefer HttpOnly plus Secure plus SameSite=Strict cookies.
Using an Online Tool
The JWT Decoder tool from DevToolkit Pro lets you inspect and verify a JWT quickly.
Steps:
- Paste the JWT string into the input box.
- The tool decodes the Header and Payload automatically and shows them as formatted JSON.
- For HS256 tokens, enter the secret key to check whether the signature is valid.
- A green marker means the signature matches. A red one means it does not.
The tool runs entirely in your browser. Your token never leaves your device.
FAQ
What is the difference between JWT and Session?
Sessions are stateful. The server stores session data for each user. JWT is stateless. All the information lives inside the token, and the server only needs the secret key to verify it. Sessions make it easy to revoke access on demand. JWT fits distributed architectures naturally.
Can the signature be cracked?
HS256 uses HMAC-SHA256, which is cryptographically sound. The real risk is the key. If it is long and random, brute forcing is impractical. If it is something like "secret", it breaks in seconds.
Should I store the token in a Cookie or LocalStorage?
It depends. Use HttpOnly cookies when you need XSS protection. Use LocalStorage when the frontend needs to read the token. Either way, always transmit over HTTPS.
Can JWT be encrypted?
Standard JWT only signs the payload. It does not encrypt it. Anyone who gets the token can decode the Base64URL and read the contents. If you need confidentiality, use JWE (JSON Web Encryption).
Article by DevToolkit Pro. Visit our homepage for more developer tools.
← Back to Blog