JSON Web Tokens (JWT) have become a standard method for securely transmitting information between parties as a JSON object. They are widely used in modern identity and access management solutions to carry claims and authorize users. However, correctly decoding and validating JWTs is critical to maintaining security.
This article explains the difference between decoding and validation, walks through secure JWT signature verification, and provides best practices for safe JWT handling.
JWT Structure Overview
A JWT consists of three base64url-encoded parts separated by dots:
header.payload.signature
- Header: Contains metadata about the token type and signing algorithm.
- Payload: Contains the claims or statements about an entity (usually the user) and additional data.
- Signature: Ensures token integrity and authenticity by signing the encoded header and payload.
Example JWT:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNjI3MDM1MjAwfQ.XYZ_SIGNATURE_HERE
Decoding JWT: What It Really Means
Decoding a JWT means base64url decoding the header and payload parts to readable JSON.
This operation is trivial and does not guarantee that the token is valid, authentic, or unmodified.
For example, decoding the header:
{
"alg": "RS256",
"typ": "JWT"
}
And the payload:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1627035200
}
You can decode JWTs in many languages using libraries or by manual base64url decoding.
Important
Decoding alone is not sufficient for security. Do not trust any claims without validating the token’s signature and expiration.
Validating JWT: Signature and Claims
1. Signature Verification
JWTs use cryptographic signatures (e.g., RS256, HS256) to protect against tampering.
To validate:
- Extract the header and payload.
- Using the signing algorithm, verify the signature against the known public key (for asymmetric algorithms like RS256) or shared secret (for symmetric algorithms like HS256).
- Reject tokens with invalid or missing signatures.
Example using Java and the popular library java-jwt
(Auth0):
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
public class JwtValidator {
public static void main(String[] args) {
String token = "eyJ..."; // JWT token string
String publicKeyPem = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkq...\n-----END PUBLIC KEY-----";
try {
Algorithm algorithm = Algorithm.RSA256(RSAKeyProviderUtil.getPublicKey(publicKeyPem), null);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token); // Verifies signature and throws if invalid
System.out.println("Token is valid. Subject: " + jwt.getSubject());
} catch (Exception e) {
System.err.println("Invalid JWT: " + e.getMessage());
}
}
}
2. Claim Validation
Beyond signature, validate important claims:
exp
(Expiration Time): Token should not be expired.nbf
(Not Before): Token should not be used before this time.iss
(Issuer): Token issuer should match your trusted issuer.aud
(Audience): Token audience should include your client/service identifier.
Most JWT libraries support claim validation as part of the verification process.
Common Mistakes and Security Pitfalls
- Trusting decoded tokens without verification: Always validate signature and claims before use.
- Using
alg: none
: Some JWTs can declare no signature; never accept these unless explicitly allowed. - Ignoring token expiration: Always check
exp
to prevent replay attacks. - Hardcoding secrets: Use secure vaults or environment variables for secrets and keys.
Handling Expired or Tampered Tokens
Your application should reject expired or tampered tokens and force users to reauthenticate or obtain new tokens via refresh flows.
Implement logging and alerting for repeated invalid token attempts to detect possible attacks.
Summary
Step | Description |
---|---|
Decode | Base64url decode header and payload (no trust) |
Verify Signature | Use correct algorithm and keys to verify |
Validate Claims | Check expiration, issuer, audience, etc. |
Reject Invalid Token | Enforce security policies strictly |
JWTs are powerful but must be handled with care. Correct decoding and validation prevent unauthorized access and protect your system’s integrity.
By mastering secure JWT handling, you ensure robust authentication and authorization mechanisms aligned with modern identity best practices.