Auditor de Segurança JWT
Audite tokens JWT para vulnerabilidades de algoritmo e claims faltantes
What is JWT Security Auditing?
JWT (JSON Web Token) security auditing is the systematic process of analyzing token configurations, signing algorithms, and claim structures to identify vulnerabilities that could allow unauthorized access, token forgery, or privilege escalation. While tools like JWT decoders parse tokens and JWT verifiers check signatures, a security auditor evaluates the overall security posture of a JWT implementation — detecting misconfigurations that remain invisible to basic validation.
The JWT specification (RFC 7519) and the JSON Web Algorithms specification (RFC 7518) provide flexibility in algorithm selection and claim usage. This flexibility is a double-edged sword: it enables diverse use cases but also introduces attack surfaces when implementers choose weak configurations. A JWT security auditor flags these weaknesses before attackers exploit them — covering algorithm confusion attacks, weak signing keys, missing critical claims, and insecure header parameters that standard validators silently accept.
Critical JWT Vulnerability Types
JWT implementations are susceptible to several well-documented attack vectors. A thorough security audit checks for each of these vulnerabilities:
-
Algorithm "none" attack (CVE-2015-9235): The JWT spec allows
"alg": "none"for unsecured tokens. Attackers modify a signed token's header to{"alg": "none"}and strip the signature. Libraries that honor the header's algorithm claim without server-side enforcement will accept the forged token as valid — granting unauthorized access without any cryptographic verification. - HMAC/RSA confusion (CVE-2016-10555): When a server expects RSA-signed tokens (RS256) but a library also accepts HMAC (HS256), an attacker can sign a forged token using the server's public RSA key as the HMAC secret. Since the public key is available to everyone, this effectively allows anyone to forge valid tokens. The audit detects tokens using symmetric algorithms where asymmetric signing is expected.
-
Weak HMAC signing keys: HMAC-SHA256 requires a key with at least 256 bits of entropy
to resist brute-force attacks. Keys derived from short passwords, dictionary words, or predictable
values (like
"secret"or"password123") can be cracked offline using tools like hashcat. The auditor estimates key entropy and flags keys shorter than the algorithm's hash output. -
Missing expiration claims: Tokens without an
exp(expiration) claim remain valid indefinitely. If compromised through log leakage, stolen cookies, or XSS, they provide permanent unauthorized access. The auditor flags tokens lackingexp,nbf(not before), andiat(issued at) temporal claims. -
Unvalidated claims: Claims like
sub(subject),iss(issuer), andaud(audience) must be validated server-side. Tokens with overly permissive audience values, missing issuer constraints, or user-controlled claims that feed into authorization decisions represent privilege escalation risks.
Security Best Practices for JWT Implementation
Beyond detecting vulnerabilities, a JWT security audit validates that implementation follows established cryptographic best practices:
-
Explicit algorithm allowlist: Never rely on the token's
algheader to select the verification algorithm. Maintain a server-side allowlist of accepted algorithms and reject tokens specifying anything outside that list. This prevents both the "none" attack and algorithm confusion entirely. - Asymmetric signing for distributed systems: Use RS256, RS384, ES256, or EdDSA for systems where multiple services verify tokens but only one service issues them. Asymmetric algorithms ensure that verifiers (holding only the public key) cannot forge tokens — eliminating the shared-secret distribution problem of HMAC.
-
Short token lifetimes: Set
expto the shortest duration acceptable for your use case — typically 5 to 15 minutes for access tokens. Use refresh tokens (stored server-side) to issue new access tokens without requiring re-authentication. Short lifetimes limit the damage window if a token is compromised. -
Audience and issuer validation: Always verify
audmatches your service identifier andissmatches your expected identity provider. Without these checks, a token issued for Service A could be replayed against Service B if both share the same signing key. -
Key rotation and
kidheader: Rotate signing keys periodically and use thekid(Key ID) header to identify which key signed a given token. This enables zero-downtime key rotation — new tokens use the new key while existing tokens remain verifiable with the old key until they expire. - Avoid sensitive data in payloads: JWT payloads are Base64URL-encoded, not encrypted. Anyone with access to the token can decode and read all claims. Never include passwords, credit card numbers, personal health information, or cryptographic secrets in JWT payloads. Use JWE (JSON Web Encryption) if payload confidentiality is required.
Audit Checklist: What the Security Auditor Evaluates
A comprehensive JWT security audit evaluates tokens across multiple dimensions. This tool performs the following automated checks on any JWT you provide:
-
Algorithm strength assessment: Classifies the
algheader value into categories — insecure (none), deprecated (HS256with weak key), acceptable (RS256,HS256with strong key), or recommended (ES256,EdDSA). Flags tokens using algorithms with known weaknesses. -
Temporal claim analysis: Verifies presence of
exp,iat, andnbf. Calculates token lifetime and flags excessively long durations (greater than 24 hours for access tokens). Checks thatnbfprecedesexpand thatiatis not in the future. -
Claim completeness scoring: Evaluates whether essential claims (
iss,sub,aud,jti) are present. Missing claims reduce the security score and generate specific recommendations for what to add and why. -
Header parameter inspection: Detects dangerous header parameters like
jku(JWK Set URL) andx5u(X.509 URL) that point to attacker-controlled key sources. Flagsjwkembedded keys that bypass key management entirely. - Payload sensitivity scan: Identifies claims that may contain sensitive data (email addresses, internal IDs, role arrays) and warns about information exposure in unencrypted tokens.
The auditor produces a security score from 0 to 100 along with prioritized recommendations, enabling developers to systematically harden their JWT implementation before deploying to production.
JWT Security Auditor vs Related JWT Tools
The JWT ecosystem includes several tools with distinct purposes. Understanding the difference prevents gaps in your security workflow:
-
JWT Decoder: Parses the token structure and displays the header and payload as
readable JSON. Does not evaluate security — a decoder happily displays a token signed with
"alg": "none"without raising any concern. - JWT Generator: Creates new tokens with specified claims and algorithm. Useful for testing but does not assess whether the chosen configuration is secure.
- JWT Verifier: Checks that a token's signature is valid against a provided key. Answers "was this token signed by this key?" but not "is this token configuration safe?"
- JWT Security Auditor (this tool): Evaluates the security posture of a token's configuration. Answers "what are the vulnerabilities in this token?" and "how do I fix them?" Combines algorithm analysis, claim assessment, header inspection, and best-practice validation into a single comprehensive security report.
In a mature security workflow, all four tools serve complementary roles: generate tokens with proper configuration, decode them for debugging, verify signatures in production, and audit the overall security posture during development and code review.
Code Examples
JWT Security Audit: Detecting Vulnerabilities in Token Configuration
// JWT Security Audit — detect common vulnerabilities
function auditJwtSecurity(token) {
const [headerB64, payloadB64] = token.split('.');
const header = JSON.parse(atob(headerB64));
const payload = JSON.parse(atob(payloadB64));
const findings = [];
// Check 1: Algorithm "none" attack
if (header.alg === 'none' || header.alg === 'None') {
findings.push({
severity: 'critical',
issue: 'Algorithm set to "none" — token has no signature',
fix: 'Use RS256, ES256, or EdDSA with server-side algorithm enforcement'
});
}
// Check 2: Weak symmetric algorithms without key strength context
const weakAlgorithms = ['HS256', 'HS384', 'HS512'];
if (weakAlgorithms.includes(header.alg) && header.kid === undefined) {
findings.push({
severity: 'warning',
issue: `Symmetric algorithm ${header.alg} without key ID (kid)`,
fix: 'Use asymmetric signing (RS256/ES256) or add kid for key rotation'
});
}
// Check 3: Missing expiration claim
if (!payload.exp) {
findings.push({
severity: 'high',
issue: 'Missing "exp" claim — token never expires',
fix: 'Add exp claim with short lifetime (300-900 seconds for access tokens)'
});
}
// Check 4: Excessive token lifetime
if (payload.exp && payload.iat) {
const lifetimeHours = (payload.exp - payload.iat) / 3600;
if (lifetimeHours > 24) {
findings.push({
severity: 'medium',
issue: `Token lifetime is ${lifetimeHours.toFixed(1)} hours (>24h)`,
fix: 'Reduce to 15 minutes for access tokens, use refresh tokens'
});
}
}
// Check 5: Missing issuer/audience claims
if (!payload.iss) {
findings.push({
severity: 'medium',
issue: 'Missing "iss" claim — cannot verify token origin',
fix: 'Add iss claim matching your identity provider URL'
});
}
if (!payload.aud) {
findings.push({
severity: 'medium',
issue: 'Missing "aud" claim — token accepted by any service',
fix: 'Add aud claim with target service identifier'
});
}
// Check 6: Dangerous header parameters
const dangerousHeaders = ['jku', 'x5u', 'jwk'];
for (const param of dangerousHeaders) {
if (header[param]) {
findings.push({
severity: 'critical',
issue: `Header contains "${param}" — external key injection risk`,
fix: `Remove ${param} and use server-side key resolution via kid`
});
}
}
// Calculate security score (100 = no issues found)
const severityWeights = { critical: 30, high: 20, medium: 10, warning: 5 };
const deductions = findings.reduce(
(sum, f) => sum + (severityWeights[f.severity] || 5), 0
);
const score = Math.max(0, 100 - deductions);
return { score, findings, algorithm: header.alg, claims: Object.keys(payload) };
}
// Example usage
const token = 'eyJhbGciOiJub25lIn0.eyJzdWIiOiIxMjM0In0.';
const audit = auditJwtSecurity(token);
// → { score: 20, findings: [{severity: 'critical', issue: 'Algorithm set to "none"'...}], ... }Standards & Specifications
- RFC 7519 — JSON Web Token (JWT) specification — defines token structure, registered claims, and processing rules
- RFC 7518 — JSON Web Algorithms (JWA) — specifies cryptographic algorithms for JWS and JWE including HMAC, RSA, and ECDSA
- RFC 7515 — JSON Web Signature (JWS) — defines the signature mechanism and header parameters used in signed JWTs
- RFC 8725 — JWT Best Current Practices — security recommendations addressing known JWT vulnerabilities and attack vectors