[{"data":1,"prerenderedAt":394},["ShallowReactive",2],{"blog-vulnerabilities/broken-auth":3},{"id":4,"title":5,"body":6,"category":370,"date":371,"dateModified":371,"description":372,"draft":373,"extension":374,"faq":375,"featured":373,"headerVariant":379,"image":380,"keywords":380,"meta":381,"navigation":382,"ogDescription":383,"ogTitle":380,"path":384,"readTime":385,"schemaOrg":386,"schemaType":387,"seo":388,"sitemap":389,"stem":390,"tags":391,"twitterCard":392,"__hash__":393},"blog/blog/vulnerabilities/broken-auth.md","Broken Authentication Explained: When Login Security Fails",{"type":7,"value":8,"toc":356},"minimark",[9,16,21,24,43,47,52,67,76,80,83,92,101,105,172,176,185,194,198,201,211,220,224,227,288,297,325,344],[10,11,12],"tldr",{},[13,14,15],"p",{},"Broken authentication covers any weakness in login and session management. Common issues include weak password policies, missing rate limiting, insecure password storage, and predictable session tokens. For most apps, use established auth providers (Clerk, Auth0, Supabase Auth) instead of building your own. If you must build auth, hash passwords with bcrypt, implement rate limiting, and use secure session management.",[17,18,20],"h2",{"id":19},"what-is-broken-authentication","What Is Broken Authentication?",[13,22,23],{},"Broken authentication is a category of vulnerabilities that affect how users log in and stay logged in. When authentication is broken, attackers can:",[25,26,27,31,34,37,40],"ul",{},[28,29,30],"li",{},"Guess or brute-force passwords without rate limiting",[28,32,33],{},"Steal or hijack session tokens",[28,35,36],{},"Bypass authentication entirely",[28,38,39],{},"Take over accounts through password reset flaws",[28,41,42],{},"Access accounts through credential stuffing (using leaked passwords)",[17,44,46],{"id":45},"common-authentication-vulnerabilities","Common Authentication Vulnerabilities",[48,49,51],"h3",{"id":50},"_1-weak-password-storage","1. Weak Password Storage",[53,54,56],"code-block",{"label":55},"DANGEROUS: Storing passwords wrong",[57,58,63],"pre",{"className":59,"code":61,"language":62},[60],"language-text","// CRITICAL VULNERABILITY: Plain text passwords\nconst user = await db.user.create({\n  data: { email, password }  // Password stored as-is!\n});\n\n// WRONG: Using weak hashing\nconst hash = crypto.createHash('md5').update(password).digest('hex');\n\n// WRONG: Missing salt\nconst hash = crypto.createHash('sha256').update(password).digest('hex');\n","text",[64,65,61],"code",{"__ignoreMap":66},"",[53,68,70],{"label":69},"SECURE: Proper password hashing",[57,71,74],{"className":72,"code":73,"language":62},[60],"import bcrypt from 'bcrypt';\n\n// Hashing a password (on signup)\nconst saltRounds = 12;\nconst hashedPassword = await bcrypt.hash(password, saltRounds);\n\n// Verifying a password (on login)\nconst isValid = await bcrypt.compare(password, user.hashedPassword);\n",[64,75,73],{"__ignoreMap":66},[48,77,79],{"id":78},"_2-no-rate-limiting","2. No Rate Limiting",[13,81,82],{},"Without rate limiting, attackers can try thousands of passwords:",[53,84,86],{"label":85},"Vulnerable endpoint",[57,87,90],{"className":88,"code":89,"language":62},[60],"// Attacker can send unlimited login attempts\napp.post('/api/login', async (req, res) => {\n  const { email, password } = req.body;\n  const user = await authenticate(email, password);\n  // No rate limiting = brute force attacks work\n});\n",[64,91,89],{"__ignoreMap":66},[53,93,95],{"label":94},"Protected with rate limiting",[57,96,99],{"className":97,"code":98,"language":62},[60],"import rateLimit from 'express-rate-limit';\n\nconst loginLimiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutes\n  max: 5, // 5 attempts per window\n  message: 'Too many login attempts, please try again later',\n  standardHeaders: true,\n  legacyHeaders: false,\n});\n\napp.post('/api/login', loginLimiter, async (req, res) => {\n  // Now protected against brute force\n});\n",[64,100,98],{"__ignoreMap":66},[48,102,104],{"id":103},"_3-insecure-session-management","3. Insecure Session Management",[106,107,108,124],"table",{},[109,110,111],"thead",{},[112,113,114,118,121],"tr",{},[115,116,117],"th",{},"Vulnerability",[115,119,120],{},"Problem",[115,122,123],{},"Fix",[125,126,127,139,150,161],"tbody",{},[112,128,129,133,136],{},[130,131,132],"td",{},"Predictable session IDs",[130,134,135],{},"Attackers can guess valid sessions",[130,137,138],{},"Use cryptographically random IDs",[112,140,141,144,147],{},[130,142,143],{},"Session in URL",[130,145,146],{},"Token leaked in browser history, referrer",[130,148,149],{},"Use HttpOnly cookies",[112,151,152,155,158],{},[130,153,154],{},"No session expiration",[130,156,157],{},"Stolen sessions work forever",[130,159,160],{},"Set reasonable expiration times",[112,162,163,166,169],{},[130,164,165],{},"Session not invalidated on logout",[130,167,168],{},"Old sessions still work",[130,170,171],{},"Destroy session server-side on logout",[48,173,175],{"id":174},"_4-insecure-password-reset","4. Insecure Password Reset",[53,177,179],{"label":178},"Vulnerable password reset",[57,180,183],{"className":181,"code":182,"language":62},[60],"// VULNERABLE: Predictable reset tokens\nconst resetToken = Date.now().toString();\nconst resetUrl = `/reset?token=${resetToken}`;\n\n// VULNERABLE: No expiration\nawait db.passwordReset.create({\n  data: { userId: user.id, token: resetToken }\n  // Missing: expiresAt field\n});\n\n// VULNERABLE: Token not invalidated after use\n// User could reuse the same reset link\n",[64,184,182],{"__ignoreMap":66},[53,186,188],{"label":187},"Secure password reset",[57,189,192],{"className":190,"code":191,"language":62},[60],"import crypto from 'crypto';\n\n// Generate secure random token\nconst resetToken = crypto.randomBytes(32).toString('hex');\nconst tokenHash = crypto.createHash('sha256').update(resetToken).digest('hex');\n\n// Store hashed token with expiration\nawait db.passwordReset.create({\n  data: {\n    userId: user.id,\n    tokenHash,\n    expiresAt: new Date(Date.now() + 3600000) // 1 hour\n  }\n});\n\n// After password reset, delete the token\nawait db.passwordReset.delete({ where: { tokenHash } });\n",[64,193,191],{"__ignoreMap":66},[17,195,197],{"id":196},"authentication-in-ai-generated-code","Authentication in AI-Generated Code",[13,199,200],{},"AI assistants frequently generate authentication code with critical vulnerabilities:",[202,203,204],"warning-box",{},[13,205,206,210],{},[207,208,209],"strong",{},"Common AI auth mistakes:"," Plain text passwords, hardcoded secrets, missing rate limiting, JWT tokens without expiration, predictable session IDs, and no CSRF protection on login forms.",[53,212,214],{"label":213},"What AI might generate",[57,215,218],{"className":216,"code":217,"language":62},[60],"// AI often generates vulnerable auth patterns\napp.post('/login', async (req, res) => {\n  const user = await db.user.findFirst({\n    where: {\n      email: req.body.email,\n      password: req.body.password  // Plain text comparison!\n    }\n  });\n\n  if (user) {\n    res.cookie('userId', user.id);  // Insecure cookie!\n    res.json({ success: true });\n  }\n});\n",[64,219,217],{"__ignoreMap":66},[17,221,223],{"id":222},"better-approach-use-auth-providers","Better Approach: Use Auth Providers",[13,225,226],{},"For most applications, using established authentication services is safer:",[106,228,229,242],{},[109,230,231],{},[112,232,233,236,239],{},[115,234,235],{},"Provider",[115,237,238],{},"Best For",[115,240,241],{},"Features",[125,243,244,255,266,277],{},[112,245,246,249,252],{},[130,247,248],{},"Clerk",[130,250,251],{},"Next.js apps, fast setup",[130,253,254],{},"Pre-built components, MFA, social login",[112,256,257,260,263],{},[130,258,259],{},"Auth0",[130,261,262],{},"Enterprise, complex requirements",[130,264,265],{},"SSO, compliance features, custom rules",[112,267,268,271,274],{},[130,269,270],{},"Supabase Auth",[130,272,273],{},"Full-stack with Supabase",[130,275,276],{},"Row-level security integration, social login",[112,278,279,282,285],{},[130,280,281],{},"NextAuth.js",[130,283,284],{},"Self-hosted, flexible",[130,286,287],{},"Many providers, database sessions",[289,290,291],"success-box",{},[13,292,293,296],{},[207,294,295],{},"Auth providers handle:"," Password hashing, secure sessions, rate limiting, MFA, password reset flows, social login, and security updates. This lets you focus on your app instead of security implementation.",[298,299,300,307,313,319],"faq-section",{},[301,302,304],"faq-item",{"question":303},"What is broken authentication?",[13,305,306],{},"Broken authentication refers to weaknesses in login and session management that let attackers compromise passwords, keys, or session tokens. This can lead to account takeover, unauthorized access, or identity impersonation.",[301,308,310],{"question":309},"Should I build my own authentication system?",[13,311,312],{},"For most applications, using established authentication providers like Clerk, Auth0, or NextAuth is safer than building your own. These services handle security complexities like password hashing, session management, and brute force protection.",[301,314,316],{"question":315},"Is storing passwords in plain text really that bad?",[13,317,318],{},"Yes, it's critical. If your database is breached, attackers get everyone's passwords immediately. Since users reuse passwords, this often leads to account compromises on other sites. Always hash passwords with bcrypt, argon2, or scrypt.",[301,320,322],{"question":321},"What's the difference between authentication and authorization?",[13,323,324],{},"Authentication verifies who you are (login). Authorization determines what you can do (permissions). Both are important: broken authentication lets attackers log in; broken authorization lets logged-in users access things they shouldn't.",[326,327,328,334,339],"related-articles",{},[329,330],"related-card",{"description":331,"href":332,"title":333},"Proper password storage","/blog/how-to/hash-passwords-securely","How to Hash Passwords",[329,335],{"description":336,"href":337,"title":338},"Token security issues","/blog/vulnerabilities/jwt-vulnerabilities","JWT Vulnerabilities",[329,340],{"description":341,"href":342,"title":343},"Using Clerk safely","/blog/guides/clerk","Clerk Security Guide",[345,346,349,353],"cta-box",{"href":347,"label":348},"/","Start Free Scan",[17,350,352],{"id":351},"check-your-authentication-security","Check Your Authentication Security",[13,354,355],{},"Our scanner tests your login system for common vulnerabilities.",{"title":66,"searchDepth":357,"depth":357,"links":358},2,[359,360,367,368,369],{"id":19,"depth":357,"text":20},{"id":45,"depth":357,"text":46,"children":361},[362,364,365,366],{"id":50,"depth":363,"text":51},3,{"id":78,"depth":363,"text":79},{"id":103,"depth":363,"text":104},{"id":174,"depth":363,"text":175},{"id":196,"depth":357,"text":197},{"id":222,"depth":357,"text":223},{"id":351,"depth":357,"text":352},"vulnerabilities","2026-01-12","Broken authentication lets attackers bypass login systems, take over accounts, or impersonate users. Learn the common auth failures in vibe-coded apps and how to fix them.",false,"md",[376,377,378],{"question":303,"answer":306},{"question":309,"answer":312},{"question":315,"answer":318},"red",null,{},true,"Learn how authentication vulnerabilities work and how to secure your login system.","/blog/vulnerabilities/broken-auth","10 min read","[object Object]","TechArticle",{"title":5,"description":372},{"loc":384},"blog/vulnerabilities/broken-auth",[],"summary_large_image","dewdrJt4Il-_gGNS--tQmpm2NzE2olK5eX3P3GNMZPg",1775843926982]