Auth/SSO: What Goes Wrong and How to Avoid It
The most common errors in authentication implementations and how to build truly secure auth.
Authentication is, without a doubt, the most critical part of any web application. An error here does not just cause a visual bug; it causes data leakage, account theft, and reputation destruction. Yet, we continue making the same basic mistakes.
Error #1: Storing Tokens in LocalStorage
This is the most common error found in React tutorials.
"Receive the JWT and save it using localStorage.setItem('token', ...)."
The problem: Any JavaScript script running on your page has access to LocalStorage. If you have an XSS (Cross-Site Scripting) vulnerability—for instance, via a compromised npm dependency or poorly sanitized input—the attacker can read your token and steal the user's session.
The solution: HttpOnly Cookies.
These cookies are automatically sent by the browser in requests to your domain, but are not accessible via JavaScript. Even if an attacker manages to run a script on your page, they cannot read the cookie.
Error #2: Ignoring CSRF
By using cookies, you protect yourself from XSS (token theft), but you expose yourself to CSRF (Cross-Site Request Forgery). A malicious site can make a request to your API, and the browser will automatically send the cookie.
The solution:
- Modern frameworks like Next.js/Auth.js handle this by checking origin headers.
- SameSite cookies (
SameSite=LaxorStrict) greatly help mitigate this natively in the browser.
Error #3: Implementing Password Encryption Yourself
Never, ever implement your own password hashing. Do not use MD5. Do not use SHA-1. Do not use simple SHA-256.
The solution: Use algorithms designed for passwords, such as Argon2, Bcrypt, or Scrypt. They are intentionally slow to hinder brute-force attacks. In Node.js, libraries like argon2 or bcrypt itself are the standard.
SSO (Single Sign-On) and the "Magic Link" Problem
SSO (logging in with Google/GitHub) is great for UX. But the manual implementation of OAuth 2.0 is full of pitfalls.
A common mistake is failing to validate the state parameter to prevent replay attacks or failing to verify the signature of ID tokens (OIDC).
Always use high-level libraries (like NextAuth/Auth.js or Lucia) that abstract the OAuth handshake. If you do it manually, you will make mistakes.
Conclusion
Security is not about being "impenetrable"; it's about raising the difficulty bar for the attacker.
- Tokens in HttpOnly and Secure Cookies.
- Use mature auth libraries; don't build from scratch.
- Keep your dependencies updated.