[{"data":1,"prerenderedAt":178},["ShallowReactive",2],{"blog-vulnerabilities/jwt-vulnerabilities":3},{"id":4,"title":5,"body":6,"category":158,"date":159,"dateModified":159,"description":160,"draft":161,"extension":162,"faq":163,"featured":161,"headerVariant":164,"image":163,"keywords":163,"meta":165,"navigation":166,"ogDescription":167,"ogTitle":163,"path":168,"readTime":169,"schemaOrg":170,"schemaType":171,"seo":172,"sitemap":173,"stem":174,"tags":175,"twitterCard":176,"__hash__":177},"blog/blog/vulnerabilities/jwt-vulnerabilities.md","JWT Vulnerabilities Explained",{"type":7,"value":8,"toc":147},"minimark",[9,16,21,26,29,44,48,55,64,68,71,81,85,94,116,135],[10,11,12],"tldr",{},[13,14,15],"p",{},"JWTs are commonly used for authentication but easy to implement wrong. The main vulnerabilities are: accepting the \"none\" algorithm, using weak secrets that can be brute-forced, and algorithm confusion attacks. Always specify the allowed algorithm explicitly and use a strong secret (256+ bits for HS256).",[17,18,20],"h2",{"id":19},"common-jwt-vulnerabilities","Common JWT Vulnerabilities",[22,23,25],"h3",{"id":24},"_1-algorithm-confusion","1. Algorithm Confusion",[13,27,28],{},"Some libraries accept the algorithm from the token header instead of enforcing one. Attackers can switch from RS256 to HS256 and sign with the public key.",[30,31,33],"code-block",{"label":32},"Vulnerable: accepting algorithm from token",[34,35,40],"pre",{"className":36,"code":38,"language":39},[37],"language-text","// VULNERABLE: doesn't specify algorithm\njwt.verify(token, publicKey);\n\n// Attacker changes header to HS256 and signs with public key\n// { \"alg\": \"HS256\" } + HMAC(payload, publicKey)\n","text",[41,42,38],"code",{"__ignoreMap":43},"",[22,45,47],{"id":46},"_2-none-algorithm","2. None Algorithm",[13,49,50,51,54],{},"Old or misconfigured libraries accept ",[41,52,53],{},"alg: \"none\""," which skips signature verification entirely.",[30,56,58],{"label":57},"Token with no signature",[34,59,62],{"className":60,"code":61,"language":39},[37],"// Attacker sends:\n// Header: { \"alg\": \"none\" }\n// Payload: { \"sub\": \"admin\", \"role\": \"admin\" }\n// Signature: (empty)\n\n// Bad library accepts it as valid!\n",[41,63,61],{"__ignoreMap":43},[22,65,67],{"id":66},"_3-weak-secrets","3. Weak Secrets",[13,69,70],{},"Short or common secrets can be brute-forced. Tools like hashcat can crack weak JWT secrets quickly.",[72,73,74],"danger-box",{},[13,75,76,80],{},[77,78,79],"strong",{},"Weak secrets:"," \"secret\", \"password123\", or any string under 32 characters can be cracked. Use at least 256 bits of randomness for HS256.",[17,82,84],{"id":83},"secure-jwt-implementation","Secure JWT Implementation",[30,86,88],{"label":87},"Safe JWT verification",[34,89,92],{"className":90,"code":91,"language":39},[37],"import jwt from 'jsonwebtoken';\n\n// Always specify the algorithm explicitly\nconst decoded = jwt.verify(token, process.env.JWT_SECRET, {\n  algorithms: ['HS256'],  // Reject any other algorithm\n  issuer: 'yourapp.com',\n  audience: 'yourapp.com'\n});\n\n// Generate a strong secret (run once, save to env)\n// node -e \"console.log(require('crypto').randomBytes(32).toString('hex'))\"\n",[41,93,91],{"__ignoreMap":43},[95,96,97,104,110],"faq-section",{},[98,99,101],"faq-item",{"question":100},"Should I use HS256 or RS256?",[13,102,103],{},"HS256 (symmetric) is simpler for single services. RS256 (asymmetric) is better when multiple services verify tokens, as you can share the public key without exposing the private key.",[98,105,107],{"question":106},"How do I handle JWT expiration?",[13,108,109],{},"Use short-lived access tokens (15 min to 1 hour) with refresh tokens. Always check the exp claim and reject expired tokens.",[98,111,113],{"question":112},"Should I store JWTs in localStorage?",[13,114,115],{},"LocalStorage is vulnerable to XSS. Consider HttpOnly cookies for web apps. For SPAs, weigh the tradeoffs carefully based on your XSS risk.",[117,118,119,125,130],"related-articles",{},[120,121],"related-card",{"description":122,"href":123,"title":124},"Auth security overview","/blog/vulnerabilities/broken-auth","Broken Authentication",[120,126],{"description":127,"href":128,"title":129},"Cookie storage for JWTs","/blog/vulnerabilities/insecure-cookies","Insecure Cookies",[120,131],{"description":132,"href":133,"title":134},"Implementation walkthrough","/blog/how-to/add-authentication-nextjs","JWT Auth Guide",[136,137,140,144],"cta-box",{"href":138,"label":139},"/","Start Free Scan",[17,141,143],{"id":142},"check-your-jwt-implementation","Check Your JWT Implementation",[13,145,146],{},"Our scanner tests for common JWT vulnerabilities.",{"title":43,"searchDepth":148,"depth":148,"links":149},2,[150,156,157],{"id":19,"depth":148,"text":20,"children":151},[152,154,155],{"id":24,"depth":153,"text":25},3,{"id":46,"depth":153,"text":47},{"id":66,"depth":153,"text":67},{"id":83,"depth":148,"text":84},{"id":142,"depth":148,"text":143},"vulnerabilities","2026-01-16","JWT implementation mistakes can let attackers forge tokens or bypass authentication. Learn about algorithm confusion, weak secrets, and proper JWT validation.",false,"md",null,"red",{"noindex":166},true,"Learn about common JWT security mistakes and how to avoid them.","/blog/vulnerabilities/jwt-vulnerabilities","7 min read","[object Object]","TechArticle",{"title":5,"description":160},{"loc":168},"blog/vulnerabilities/jwt-vulnerabilities",[],"summary_large_image","NUL9ZibMp5SacccPi-VBWsw3-v61FyBqRzJuz-WkI-Y",1775843926805]