Secure JWT Authentication
JSON Web Tokens (JWT) are widely used for authentication and authorization. However, improper implementation can lead to serious security vulnerabilities including authentication bypass and token forgery. The most critical JWT vulnerability is decoding tokens without verifying their signatures, which allows attackers to forge tokens with arbitrary claims, impersonate any user, or escalate privileges.
Related CWEs: CWE-287 (Improper Authentication), CWE-345 (Insufficient Verification of Data Authenticity), CWE-347 (Improper Verification of Cryptographic Signature).
Incorrect (JavaScript jsonwebtoken - decode without verify):
const jwt = require('jsonwebtoken');
function getUserData(token) {
const decoded = jwt.decode(token, true);
if (decoded.isAdmin) {
return getAdminData();
}
}Correct (JavaScript jsonwebtoken - use verify which returns decoded payload):
const jwt = require('jsonwebtoken');
function getUserData(token, secretKey) {
const decoded = jwt.verify(token, secretKey);
if (decoded.isAdmin) {
return getAdminData();
}
}Incorrect (Python PyJWT - verify_signature disabled):
import jwt
def get_user_claims(token, key):
decoded = jwt.decode(token, key, options={"verify_signature": False})
return decodedCorrect (Python PyJWT - verify_signature enabled):
import jwt
def get_user_claims(token, key):
decoded = jwt.decode(token, key, algorithms=["HS256"])
return decodedIncorrect (Java auth0 java-jwt - decode without verify):
import com.auth0.jwt.JWT;
import com.auth0.jwt.interfaces.DecodedJWT;
public class TokenHandler {
public DecodedJWT getUserClaims(String token) {
DecodedJWT jwt = JWT.decode(token);
return jwt;
}
}Correct (Java auth0 java-jwt - verify before use):
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 TokenHandler {
public DecodedJWT getUserClaims(String token, String secret) {
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build();
DecodedJWT jwt = verifier.verify(token);
return jwt;
}
}References: