Authentication UI
The authentication UI is where security meets user experience — login, signup, password reset, and session handling. It's high-stakes on both sides: clumsy UX loses users at the door, and careless token handling exposes accounts.
Most of the security work is where you keep the token and how you handle errors. Most of the UX work is clear feedback, loading states, and not making people fight the form.
TL;DR
- Prefer
HttpOnlycookies for tokens overlocalStorage. - Gate private pages behind a protected route with a loading state.
- Offer social login and a password visibility toggle.
- Show clear errors without revealing which field was wrong (no account enumeration).
- The frontend is UX — real enforcement happens on the server.
Quick Example
A protected route that waits for auth to resolve, then redirects unauthenticated users:
Core Concepts
The flows
- Login — email/password, social, or magic link.
- Signup — registration with validation and a breach check.
- Password reset — single-use, short-lived, hashed token.
- Session — cookies or tokens, with refresh and clean logout.
Token storage
localStorage is readable by any XSS, so avoid it for sensitive tokens. Prefer HttpOnly, Secure cookies (which then need CSRF protection) and keep access tokens short-lived. See Authentication and JWT.
Protected routes
Wrap private pages so they check auth state, show a loading state while it resolves, and redirect to login (preserving the intended destination) when unauthenticated.
Best Practices
- Store tokens in
HttpOnlycookies; keep access tokens short-lived. - Clear all sensitive state on logout.
- Provide loading states on every auth action so users aren't left guessing.
- Offer social login ("Continue with Google/GitHub") and a show/hide password toggle.
- Indicate password strength on signup and screen against breached passwords. See Password Security.
Common Mistakes
Leaking which field was wrong
Storing long-lived tokens in localStorage
FAQ
Where should I store auth tokens in the browser?
Prefer HttpOnly, Secure cookies — they're not readable by JavaScript, so XSS can't steal them (you then add CSRF protection). If you must use a token in JS, keep it short-lived and in memory, never in localStorage.
How do I protect routes that require login?
Wrap them in a component that reads auth state, renders a loading indicator while it resolves, and redirects unauthenticated users to login while remembering where they were headed. Remember this is UX only — the API must independently authorize every request.
How should login errors be worded?
Generically. Saying "no account with that email" lets attackers enumerate valid accounts. Use a single "Invalid email or password" for both wrong-email and wrong-password cases, and rate-limit attempts.
Should I build auth from scratch?
Usually not. Use a vetted provider or library (Auth.js, Clerk, Supabase Auth, Auth0) for the flows and token handling, and focus your effort on the UX and integration. Rolling your own is where subtle, costly security bugs appear.
Related Topics
- Authentication — Strategies and session design
- JWT — Token validation and lifetimes
- OAuth 2.0 — Social login flows
- Password Security — Strength meters and breach checks
- Application Security — The broader threat model