[{"data":1,"prerenderedAt":268},["ShallowReactive",2],{"blog-checklists/authentication-security-checklist":3},{"id":4,"title":5,"body":6,"category":245,"date":246,"dateModified":246,"description":247,"draft":248,"extension":249,"faq":250,"featured":248,"headerVariant":253,"image":254,"keywords":254,"meta":255,"navigation":256,"ogDescription":257,"ogTitle":254,"path":258,"readTime":254,"schemaOrg":259,"schemaType":260,"seo":261,"sitemap":262,"stem":263,"tags":264,"twitterCard":266,"__hash__":267},"blog/blog/checklists/authentication-security-checklist.md","Authentication Security Checklist: 29-Item Guide",{"type":7,"value":8,"toc":239},"minimark",[9,16,19,22,46,65,87,115,141,160,178,183,186,208,227],[10,11,12],"tldr",{},[13,14,15],"p",{},"Use a proven auth library (NextAuth, Clerk, Auth0). If rolling your own: hash passwords with bcrypt/argon2, use secure session cookies, implement rate limiting on login, and make password reset tokens single-use and time-limited. 8 critical items must be fixed before launch, 14 important items within the first week, and 7 recommended items when you can.",[13,17,18],{},"Auth is one of those things that seems straightforward until you get it wrong and suddenly someone else is logged into your users' accounts. Even if you are using a third-party auth provider, there are still plenty of ways to misconfigure things. Go through each item here and actually verify it works -- don't just assume.",[20,21],"print-button",{},[23,24,26,31,35,39,43],"checklist-section",{"title":25},"Quick Checklist (5 Critical Items)",[27,28],"checklist-item",{"description":29,"label":30},"Never store plain text or use MD5/SHA1","Passwords hashed with bcrypt or Argon2",[27,32],{"description":33,"label":34},"Prevents JavaScript access and requires HTTPS","Session cookies are HttpOnly and Secure",[27,36],{"description":37,"label":38},"Limit attempts per IP and per account","Rate limiting on login attempts",[27,40],{"description":41,"label":42},"Token is invalidated after use","Password reset tokens are single-use",[13,44,45],{},"::checklist-item{label=\"Generic error messages on login\" description=\"\"Invalid credentials\" not \"User not found\" or \"Wrong password\"\"}\n::",[23,47,50,53,57,61],{"title":48,"count":49},"Password Security","4",[27,51],{"description":52,"label":30},"Never store plain text or use MD5/SHA1. How to hash passwords securely",[27,54],{"description":55,"label":56},"At least 8 characters, recommend 12+. How to set password requirements","Minimum password length enforced",[27,58],{"description":59,"label":60},"Use HaveIBeenPwned API or similar. How to check breached passwords","Check against breached password list",[27,62],{"description":63,"label":64},"Password hints can leak information. Password security best practices","No password hints stored",[23,66,69,72,75,79,83],{"title":67,"count":68},"Login Security","5",[27,70],{"description":71,"label":38},"Limit attempts per IP and per account. How to implement rate limiting",[13,73,74],{},"::checklist-item{label=\"Generic error messages\" description=\"\"Invalid credentials\" not \"User not found\" or \"Wrong password\". How to secure error messages\"}\n::",[27,76],{"description":77,"label":78},"Temporary lockout after 5-10 failed attempts. How to implement account lockout","Account lockout after failed attempts",[27,80],{"description":81,"label":82},"Add after failed attempts or for suspicious behavior. How to add CAPTCHA","CAPTCHA on login form",[27,84],{"description":85,"label":86},"Log successful and failed logins for security monitoring. How to log security events","Login activity logging",[23,88,91,95,99,103,107,111],{"title":89,"count":90},"Session Management","6",[27,92],{"description":93,"label":94},"Prevents JavaScript access to session cookie. How to secure session cookies","Session cookies are HttpOnly",[27,96],{"description":97,"label":98},"Only sent over HTTPS. How to secure session cookies","Session cookies are Secure",[27,100],{"description":101,"label":102},"Use Lax or Strict to prevent CSRF. How to prevent CSRF","SameSite attribute set",[27,104],{"description":105,"label":106},"Generate new session ID after successful login. How to prevent session fixation","Session regeneration on login",[27,108],{"description":109,"label":110},"Auto-logout after inactivity period. How to configure session timeout","Session timeout configured",[27,112],{"description":113,"label":114},"Session is destroyed server-side, not just cookie deleted. How to implement secure logout","Logout invalidates session",[23,116,118,122,126,130,133,137],{"title":117,"count":90},"Password Reset",[27,119],{"description":120,"label":121},"Use crypto.randomBytes or equivalent. How to generate secure tokens","Reset tokens are cryptographically random",[27,123],{"description":124,"label":125},"Token is invalidated after use. How to implement single-use tokens","Reset tokens are single-use",[27,127],{"description":128,"label":129},"1 hour or less is recommended. How to configure token expiration","Reset tokens expire quickly",[13,131,132],{},"::checklist-item{label=\"Same response for existing/non-existing emails\" description=\"\"If an account exists, you'll receive an email\". How to prevent account enumeration\"}\n::",[27,134],{"description":135,"label":136},"Prevent email bombing and enumeration. How to rate limit reset requests","Rate limiting on reset requests",[27,138],{"description":139,"label":140},"Force re-login on all devices after password change. How to invalidate all sessions","All sessions invalidated on password change",[23,142,144,148,152,156],{"title":143,"count":49},"OAuth/Social Login",[27,145],{"description":146,"label":147},"Prevents CSRF attacks on OAuth flow. How to secure OAuth","State parameter used and verified",[27,149],{"description":150,"label":151},"No wildcards in OAuth redirect configurations. How to configure OAuth redirects","Redirect URIs are exact matches",[27,153],{"description":154,"label":155},"Only request permissions you actually need. How to choose OAuth scopes","Minimum scopes requested",[27,157],{"description":158,"label":159},"Prevent account takeover via unverified OAuth email. How to verify OAuth emails","Email verified before account linking",[23,161,163,167,170,174],{"title":162,"count":49},"JWT Security (if applicable)",[27,164],{"description":165,"label":166},"At least 256 bits of entropy. How to generate JWT secrets","Strong secret key",[13,168,169],{},"::checklist-item{label=\"Algorithm specified and verified\" description=\"Prevent \"none\" algorithm attacks. How to prevent JWT algorithm attacks\"}\n::",[27,171],{"description":172,"label":173},"Access tokens should be short-lived (15-60 min). How to configure JWT expiration","Short expiration times",[27,175],{"description":176,"label":177},"Issue new refresh token on each use. How to implement refresh token rotation","Refresh token rotation",[179,180,182],"h2",{"id":181},"authentication-best-practices","Authentication Best Practices",[13,184,185],{},"If possible, use a proven authentication library or service like NextAuth, Clerk, or Auth0 rather than implementing auth from scratch. These solutions handle many security edge cases automatically.",[187,188,189,196,202],"faq-section",{},[190,191,193],"faq-item",{"question":192},"What hashing algorithm should I use for passwords?",[13,194,195],{},"Use bcrypt or Argon2 for password hashing. Never use MD5, SHA1, or plain SHA256. These dedicated password hashing algorithms are designed to be slow and include salting, which protects against rainbow table and brute force attacks.",[190,197,199],{"question":198},"Should I use JWT or session cookies?",[13,200,201],{},"Both can be secure if implemented correctly. JWTs are stateless and good for APIs, but can't be revoked easily. Session cookies stored in HttpOnly cookies with database-backed sessions allow revocation but require server-side storage. Choose based on your revocation needs.",[190,203,205],{"question":204},"How long should password reset tokens last?",[13,206,207],{},"Password reset tokens should expire within 1 hour or less. They should be single-use (invalidated after the password is changed) and cryptographically random (at least 32 bytes). Always hash the token before storing it in the database.",[209,210,211,217,222],"related-articles",{},[212,213],"related-card",{"description":214,"href":215,"title":216},"Complete guide to auth security","/blog/guides/auth0","Authentication Guide",[212,218],{"description":219,"href":220,"title":221},"Secure your API endpoints","/blog/checklists/api-security-checklist","API Security Checklist",[212,223],{"description":224,"href":225,"title":226},"Step-by-step password hashing","/blog/how-to/hash-passwords-securely","How to Hash Passwords",[228,229,232,236],"cta-box",{"href":230,"label":231},"/","Start Free Scan",[179,233,235],{"id":234},"scan-your-authentication","Scan Your Authentication",[13,237,238],{},"Our scanner checks for common auth vulnerabilities and misconfigurations.",{"title":240,"searchDepth":241,"depth":241,"links":242},"",2,[243,244],{"id":181,"depth":241,"text":182},{"id":234,"depth":241,"text":235},"checklists","2026-01-26","Complete authentication security checklist. Password handling, session management, OAuth configuration, MFA, and secure password reset flows.",false,"md",[251,252],{"question":192,"answer":195},{"question":198,"answer":201},"green",null,{},true,"Complete auth security checklist. Passwords, sessions, OAuth, MFA.","/blog/checklists/authentication-security-checklist","[object Object]","HowTo",{"title":5,"description":247},{"loc":258},"blog/checklists/authentication-security-checklist",[265],"Security Checklist","summary_large_image","MUFUzFY43p5nCb1BV73uS892OaDD_ZdEOzfoxXuZ_eQ",1775843918547]