Security Glossary

JWT Security

JWT security encompasses the practices and potential pitfalls of using JSON Web Tokens for authentication and authorization, including proper signing, validation, and storage to prevent token forgery and information leakage.

Understanding JWT Security

JSON Web Tokens (JWTs) are a widely used format for authentication tokens. A JWT consists of three base64-encoded parts: a header (specifying the algorithm), a payload (containing claims like user ID and expiration), and a signature (proving the token has not been tampered with). JWTs are self-contained — the server can validate them without a database lookup.

JWT vulnerabilities emerge from implementation mistakes. The "none" algorithm attack occurs when a server accepts JWTs with the algorithm set to "none," allowing unsigned tokens. Algorithm confusion happens when a server configured for RSA verification can be tricked into using HMAC with the public key as the secret. Missing expiration validation lets tokens work indefinitely. Weak signing secrets can be brute-forced offline.

The payload of a JWT is base64-encoded, not encrypted. Anyone who possesses a JWT can decode and read its contents. Never put sensitive information (passwords, credit card numbers, secret keys) in JWT claims. Treat the payload as public data — the signature only ensures integrity, not confidentiality.

Best practices include using strong asymmetric algorithms (RS256, ES256) instead of symmetric HMAC for systems with multiple services, setting short expiration times (15 minutes for access tokens) with longer-lived refresh tokens, validating all claims (exp, iss, aud) on every request, using a well-maintained JWT library rather than custom implementation, and storing tokens securely (httpOnly cookies for web apps, secure storage for mobile apps).

Why This Matters for Vibe-Coded Apps

AI-generated authentication often creates JWTs with weak secrets, missing expiration, or no algorithm validation. A common pattern is the AI using a short string like "secret" as the JWT signing key, or generating tokens without expiration claims. When using managed services like Supabase or Firebase, JWT handling is done correctly by the SDK, but custom JWT implementations generated by AI frequently have vulnerabilities.

If your vibe-coded app uses custom JWT authentication (not managed by Supabase, Firebase, or Auth0), audit the token generation and validation code. Verify the signing secret is long and random (at least 256 bits), the algorithm is explicitly specified during validation (not read from the token header), and expiration is set and enforced.

Real-World Examples

Auth0 JWT "none" Algorithm Vulnerability (2015)

A vulnerability in Auth0's JWT library allowed attackers to create tokens with alg: "none", which the server accepted as valid without signature verification. This meant anyone could forge tokens for any user by simply setting the algorithm to none and removing the signature.

CVE-2022-23529: jsonwebtoken Library RCE

A critical vulnerability in the popular jsonwebtoken npm package (21 million weekly downloads) allowed remote code execution through a crafted JWT secret. The flaw demonstrated how JWT library bugs can have massive blast radius due to their widespread usage in authentication systems.

Uber JWT Secret Brute Force

Researchers demonstrated that Uber's JWT signing secret could be brute-forced because it was a short, guessable string. Once the secret was known, attackers could forge JWTs for any user account. This highlighted the importance of using strong, random secrets for JWT signing.

Frequently Asked Questions

Should I store JWTs in localStorage or cookies?

For web applications, httpOnly cookies are more secure because JavaScript cannot access them, preventing XSS-based token theft. localStorage is accessible to any JavaScript on the page. However, cookie-based JWT storage requires CSRF protection. If you must use localStorage (for certain SPA architectures), ensure robust XSS protection. For mobile apps, use the platform's secure storage (Keychain on iOS, EncryptedSharedPreferences on Android).

What is the difference between access tokens and refresh tokens?

Access tokens are short-lived (typically 15 minutes) and sent with every API request. Refresh tokens are long-lived (days or weeks) and used only to obtain new access tokens. This separation limits the damage window if an access token is stolen and allows revoking access without invalidating the refresh token. Refresh tokens should be stored more securely than access tokens and should be rotated on each use.

Can I revoke a JWT?

JWTs are stateless — once issued, they are valid until expiration. You cannot invalidate a specific JWT without adding statefulness. Common approaches include maintaining a token blocklist (checked on each request), using short expiration times so compromised tokens expire quickly, storing a per-user token version in the database and incrementing it to invalidate all existing tokens, or using refresh token rotation to detect token theft.

Is RS256 better than HS256?

RS256 (RSA) uses asymmetric key pairs — only the private key can sign tokens, while any service with the public key can verify them. HS256 (HMAC) uses a shared secret that must be known by every service that validates tokens. RS256 is better for distributed systems because you do not need to share a secret with every service. HS256 is simpler for single-server applications. RS256 also prevents the algorithm confusion attack that can affect HS256 setups.

Is Your App Protected?

VAS automatically scans for vulnerabilities related to jwt security and provides detailed remediation guidance. Our scanner targets issues common in AI-generated applications.

Scans from $5, results in minutes. Get actionable fixes tailored to your stack.

Get Starter Scan