What Is a JWT Signature? (And How to Verify One)
A JWT signature cryptographically binds a token's header and payload so it can't be tampered with. Plain explanation of HMAC vs RSA signatures with verification code.
Short answer
A JWT (JSON Web Token) signature is a cryptographic tag at the end of the token that proves the token's header and payload weren't modified after the issuer signed them. It's computed by hashing header.payload with a secret (HMAC) or a private key (RSA/ECDSA). To verify, you recompute the signature with the matching secret/public key and compare. If it matches, the token is authentic; if not, it was forged or altered.
The structure
A JWT looks like this — three Base64URL-encoded blocks separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFsaWNlIn0.K2N3...
└────── header ──────┘ └────── payload ──────┘ └ signature ┘
Decode any JWT with the JWT decoder. The first two parts decode to JSON; the third is the binary signature.
How the signature is computed
For HS256 (HMAC-SHA-256), the most common algorithm:
signature = HMAC_SHA256(
base64url(header) + "." + base64url(payload),
secret
)
token = base64url(header) + "." + base64url(payload) + "." + base64url(signature)
For RS256 (RSA + SHA-256), it's an asymmetric signature using the issuer's private key — verifiers use the matching public key to check.
Algorithm choices
| Alg | Type | Verifier needs | Use when |
|---|---|---|---|
HS256 | HMAC-SHA-256 (symmetric) | The same secret used to sign | Both sides are your own services |
HS384 / HS512 | HMAC with bigger hashes | Same secret | Higher security; rarely needed |
RS256 | RSA + SHA-256 (asymmetric) | Public key only | Public-key verifiers (mobile apps, third-party services) |
ES256 | ECDSA P-256 + SHA-256 | Public key only | Same as RS256 but smaller signatures |
EdDSA | Ed25519 signatures | Public key only | Modern preferred asymmetric option |
none | No signature | (nothing) | NEVER. This is a vulnerability. |
Verifying a JWT (Node.js example)
import jwt from 'jsonwebtoken';
try {
const decoded = jwt.verify(token, secret, {
algorithms: ['HS256'], // ← whitelist explicitly
issuer: 'https://example.com',
audience: 'my-app',
});
// decoded.sub, decoded.exp, etc.
} catch (err) {
// Signature invalid, token expired, or claims didn't match
}
Critical: always pass algorithms as a whitelist. Without it, an attacker can swap alg in the header to none or HS256 (and use your public key as the secret), bypassing verification.
Common pitfalls
- "alg: none" trick — old jsonwebtoken libraries accepted unsigned tokens. Always whitelist algorithms.
- HS256 with RSA public key as secret — if a verifier accepts both HS256 and RS256 without checking, attacker can use your public key as the HMAC secret. Whitelist exactly one algorithm per use case.
- Storing the secret/private key insecurely — anyone with the HS256 secret can mint tokens. Treat it as crown-jewel data.
- Reusing keys across environments — dev/staging/prod should each have their own signing keys. A leak in dev shouldn't compromise prod.
- Decoding ≠ verifying — JWT decoder reads the payload without checking the signature. Useful for inspection, but never trust unsigned data in your application.
What the signature does NOT do
- Doesn't encrypt the payload. Anyone can decode the JWT and read the claims — never put secrets in there.
- Doesn't prevent replay. If an attacker steals a valid JWT, they can reuse it until expiry. Use short
exp+ refresh tokens. - Doesn't prove who's using it. Possession of a valid token = authentication. If the token leaks, anyone can use it.
Related tools
Decode and inspect any JWT (signature is shown but not verified): JWT decoder. Manually compute HMAC signatures: hash generator. Base64URL is JWT's encoding flavor: Base64.
Featured Tools
Try these free tools directly in your browser — no sign-up required.
JWT Decoder
Decode and inspect JSON Web Tokens (JWTs) instantly. View header, payload, and signature without a secret key. Debug authentication tokens safely.
Hash Generator
Generate cryptographic hashes for any text using MD5, SHA-1, SHA-256, SHA-512, and more. Verify data integrity and create checksums instantly online.
Base64 Encoder / Decoder
Encode text or decode Base64 strings instantly online. Convert between plain text and Base64 encoding for data URLs, authentication headers, and API tokens.