Authentication Best Practices

Easyβ€’

Authentication proves user identity and establishes a session or token lifecycle. Strong frontend answers explain how browser storage, cookies, XSS, CSRF, token expiration, and recovery flows affect the system.

Quick Decision Guide

Senior Decision Guide:

Password hashing: Hash passwords on the server with slow salted algorithms such as Argon2id or bcrypt. Never store plaintext passwords.

Sessions: HttpOnly, Secure cookies reduce JavaScript token theft, but cookie-backed auth still needs SameSite and CSRF-aware design.

JWT / bearer tokens: JWTs are not automatically safer or more scalable. Their safety depends on lifetime, storage, revocation, rotation, and where validation happens.

OAuth/OIDC: Browser-based apps should use Authorization Code + PKCE. SPAs are public clients and cannot safely store client secrets.

Frontend responsibility: Client-side checks improve UX, but authentication and authorization enforcement must be server-side.

Interview signal: Explain the threat model: XSS, CSRF, token theft, session fixation, refresh failure, logout, and multi-tab behavior.

Understanding Authentication Flow

Overview of Authentication

Authentication verifies who a user is. Session management decides how the application remembers that identity across requests. Authorization decides what the authenticated user may do.

Figure 1: Authentication Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User      β”‚         β”‚   Server     β”‚         β”‚   Database   β”‚
β”‚  Browser    β”‚         β”‚              β”‚         β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚                       β”‚                        β”‚
       β”‚ 1. Submit Credentials β”‚                        β”‚
       β”‚    (password, OAuth,  β”‚                        β”‚
       β”‚     passkey, etc.)    β”‚                        β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>                        β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 2. Look up identity / β”‚
       β”‚                       β”‚    credential record  β”‚
       β”‚                       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ <───────────────────────
       β”‚                       β”‚    User/Auth Record   β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 3. Verify proof       β”‚
       β”‚                       β”‚    of identity        β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 4. Create session or  β”‚
       β”‚                       β”‚    issue token        β”‚
       β”‚                       β”‚                        β”‚
       β”‚ <───────────────────────                        β”‚
       β”‚    Session cookie /   β”‚                        β”‚
       β”‚    token response     β”‚                        β”‚
       β”‚                       β”‚                        β”‚
       β”‚ 5. Browser carries    β”‚                        β”‚
       β”‚    credential on      β”‚                        β”‚
       β”‚    later requests     β”‚                        β”‚

Authentication Methods

1. Password-Based Authentication

β€’Username/email + password
β€’Requires slow salted password hashing on the server
β€’Needs rate limiting, reset flows, and common-password checks

2. Session-Based Authentication

β€’Server stores session state
β€’Browser usually holds an opaque session ID in an HttpOnly cookie
β€’Easier server-side revocation, but cookie flows need CSRF-aware design

3. Token-Based Authentication (JWT / Bearer Tokens)

β€’Token is sent with API requests
β€’JWT payloads are readable unless encrypted; signatures prevent tampering, not reading
β€’Lifetime, storage, rotation, and revocation determine safety

4. OAuth 2.0 + OIDC

β€’OAuth handles delegated authorization
β€’OIDC adds identity
β€’Modern browser apps should use Authorization Code + PKCE

5. MFA / Passkeys

β€’Adds stronger proof beyond passwords
β€’Reduces account takeover and phishing risk
β€’Recovery UX becomes part of the security design

Password Security

Never Store Plain Text Passwords

Figure 2: Password Storage Comparison

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              Password Storage Methods                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                          β”‚
β”‚  ❌ Plain Text                                           β”‚
β”‚  Stored: "mypassword123"                                β”‚
β”‚  Risk: Immediate compromise if database leaks            β”‚
β”‚                                                          β”‚
β”‚  ❌ Fast Hash Only                                       β”‚
β”‚  Stored: SHA256(password)                                β”‚
β”‚  Risk: Cheap offline guessing at high speed              β”‚
β”‚                                                          β”‚
β”‚  βœ… Slow Salted Password Hash                            β”‚
β”‚  Stored: Argon2id/bcrypt/scrypt(password, salt, cost)    β”‚
β”‚  Benefit: Unique per password and expensive to guess     β”‚
β”‚                                                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Password Hashing Process

Figure 3: Password Hashing Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User      β”‚         β”‚   Server     β”‚         β”‚   Database   β”‚
β”‚ Registrationβ”‚         β”‚              β”‚         β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚                       β”‚                        β”‚
       β”‚ 1. Submit Password    β”‚                        β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>                        β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 2. Generate salt      β”‚
       β”‚                       β”‚    and choose cost    β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 3. Hash with          β”‚
       β”‚                       β”‚    password hasher    β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 4. Store hash params  β”‚
       β”‚                       β”‚    + salt + hash      β”‚
       β”‚                       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
       β”‚                       β”‚                        β”‚
       β”‚ <───────────────────────                        β”‚
       β”‚    Success            β”‚                        β”‚

Use Password Hashing Algorithms

β€’Argon2id: strong modern default when available
β€’bcrypt: widely supported adaptive hashing
β€’scrypt: memory-hard alternative

Avoid fast general-purpose hashes such as raw SHA-256 for password storage.

Password Policy

β€’Prefer longer passwords/passphrases over rigid complexity theater
β€’Check against common or breached password lists
β€’Rate limit login and reset flows
β€’Avoid predictable rules that force users into patterns like "Password1!"
β€’Design password reset as carefully as login

Session Management

Session vs Token-Based Authentication

Figure 4: Session-Based Authentication Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User      β”‚         β”‚   Server     β”‚         β”‚   Session   β”‚
β”‚  Browser    β”‚         β”‚              β”‚         β”‚   Store     β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚                       β”‚                        β”‚
       β”‚ 1. Login              β”‚                        β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>                        β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 2. Create session     β”‚
       β”‚                       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ <───────────────────────
       β”‚                       β”‚    Session ID          β”‚
       β”‚                       β”‚                        β”‚
       β”‚ <───────────────────────                        β”‚
       β”‚    HttpOnly cookie    β”‚                        β”‚
       β”‚    with session ID    β”‚                        β”‚
       β”‚                       β”‚                        β”‚
       β”‚ 3. Request with       β”‚                        β”‚
       β”‚    cookie             β”‚                        β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>                        β”‚
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ 4. Validate session   β”‚
       β”‚                       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
       β”‚                       β”‚                        β”‚
       β”‚                       β”‚ <───────────────────────
       β”‚                       β”‚    Session data        β”‚
       β”‚                       β”‚                        β”‚
       β”‚ <───────────────────────                        β”‚
       β”‚    Response           β”‚                        β”‚

Figure 5: Token-Based Authentication Flow (JWT / Bearer Token)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   User      β”‚         β”‚   Server     β”‚
β”‚  Browser    β”‚         β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                       β”‚
       β”‚ 1. Login              β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
       β”‚                       β”‚
       β”‚                       β”‚ 2. Issue signed token β”‚
       β”‚                       β”‚    or bearer token    β”‚
       β”‚                       β”‚
       β”‚ <───────────────────────
       β”‚    Access token       β”‚
       β”‚                       β”‚
       β”‚ 3. Store according    β”‚
       β”‚    to threat model    β”‚
       β”‚                       β”‚
       β”‚ 4. Request with       β”‚
       β”‚    Authorization      β”‚
       β”‚    header/cookie      β”‚
       β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€>
       β”‚                       β”‚
       β”‚                       β”‚ 5. Validate token     β”‚
       β”‚                       β”‚    and permissions    β”‚
       β”‚                       β”‚
       β”‚ <───────────────────────
       β”‚    Response           β”‚
AspectServer-Side SessionsToken-Based / JWT
Server stateSession data stored server-sideMay validate locally, but revocation/rotation may still need server state
Browser storageUsually opaque ID in HttpOnly cookieHeader token, cookie, or memory depending on architecture
RevocationStraightforward: delete server sessionNeeds short lifetimes, rotation, blocklist, introspection, or server-side session layer
XSS riskHttpOnly cookie cannot be read by JS, but app can still be abused if XSS existsBrowser-readable tokens are stealable via XSS; memory storage reduces persistence but complicates reloads
CSRF riskCookie-backed auth needs SameSite/token/origin strategyAuthorization header tokens reduce classic CSRF but shift attention to XSS/storage
Best fitWeb apps, BFF architectures, strong server controlAPIs, mobile clients, distributed systems, cross-service authorization
res.cookie('session', sessionId, {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'lax', // choose Strict/Lax/None based on product flow
  maxAge: 24 * 60 * 60 * 1000 // 24 hours
});

Senior Nuance

Do not say "sessions are secure and JWTs are insecure" or the reverse. The real question is where the credential lives, how long it lasts, how it is revoked, and which attack class is most important for the product.

Authentication Methods Comparison

MethodWhat it solvesTrade-offs
PasswordsFirst-party identity proofRequires hashing, reset flow, rate limits, breach checks
SessionsServer-controlled continuityNeeds shared storage and CSRF-aware cookies
JWT / bearer tokensPortable API credentialsToken theft and revocation must be designed carefully
OAuth 2.0Delegated authorizationMore moving parts; must validate state and redirect flows
OIDCIdentity on top of OAuthID token validation and provider trust matter
MFA / PasskeysStronger account protectionRecovery and device support are product concerns

Best Practices for Implementation

Security Checklist

Password Security:

β€’Hash passwords with Argon2id, bcrypt, or scrypt
β€’Never store plaintext passwords
β€’Check common or breached password lists
β€’Rate limit login and reset flows
β€’Design password reset as carefully as login

Session / Token Handling:

β€’Prefer HttpOnly cookies for browser sessions when appropriate
β€’Use Secure cookies in production
β€’Choose SameSite based on actual cross-site flow needs
β€’Regenerate session IDs after login
β€’Expire and revoke sessions intentionally
β€’Avoid putting tokens in URLs

JWT / Bearer Token Safety:

β€’Keep lifetimes short when tokens are browser-exposed
β€’Plan refresh, rotation, logout, and revocation
β€’Do not put sensitive secrets in readable JWT payloads
β€’Treat localStorage token storage as high XSS blast radius

OAuth / OIDC:

β€’Use Authorization Code + PKCE for browser apps
β€’Validate state and nonce where applicable
β€’Do not store client secrets in the browser
β€’Handle provider outage and refresh failure cleanly

Frontend Responsibility:

β€’Client checks are for UX only
β€’Server must enforce authentication and authorization
β€’Distinguish unauthenticated, unauthorized, expired, and degraded identity states

Key Takeaways

1Authentication verifies identity; authorization controls allowed actions.
2Sessions and JWTs have different lifecycle and storage trade-offs.
3HttpOnly cookies reduce XSS token theft but require CSRF-aware design.
4JWTs are not automatically safer or better; revocation and storage matter.
5Authorization Code + PKCE is the modern OAuth baseline for browser apps.
6Frontend auth UX should handle expiration, logout, recovery, and degraded identity providers.