# How We Design Secure Login Systems: Best Practices and Patterns
Introduction
Authentication is the foundation of application security. A single vulnerability can compromise user data and your entire system. Here's how we build secure login systems that protect both users and applications.
Core Security Principles
1. Password Storage
Never Store Plain Text PasswordsAlways hash passwords using secure algorithms: - bcrypt - Industry standard, slow by design - Argon2 - Winner of Password Hashing Competition - scrypt - Memory-hard function
Implementation:const bcrypt = require('bcrypt');
const saltRounds = 12;// Hashing
const hash = await bcrypt.hash(password, saltRounds);
// Verification
const isValid = await bcrypt.compare(password, hash);
Key Points:
- Use salt rounds of 10-12 (higher = slower = more secure)
- Never reuse salts
- Never use MD5, SHA1, or SHA256 for passwords2. Session Management
Secure Session TokensBest Practices: - Use cryptographically secure random tokens - Set appropriate expiration times - Implement refresh tokens - Store sessions securely (Redis, database)Example Implementation:// Generate secure token
const crypto = require('crypto');
const sessionToken = crypto.randomBytes(32).toString('hex');// Store in Redis with expiration
await redis.setex(`session:\${sessionToken}`, 3600, userId);
Security Measures:
- HttpOnly cookies (prevent XSS)
- Secure flag (HTTPS only)
- SameSite attribute (prevent CSRF)
- Short expiration times3. Rate Limiting
Prevent Brute Force AttacksImplementation: - Limit login attempts per IP - Implement exponential backoff - Use CAPTCHA after failed attempts - Account lockout after multiple failuresExample:// Rate limiting with Redis
const attempts = await redis.incr(`login:attempts:\${ip}`);
if (attempts === 1) {
await redis.expire(`login:attempts:\${ip}`, 900); // 15 minutes
}
if (attempts > 5) {
return res.status(429).json({ error: 'Too many attempts' });
}4. Two-Factor Authentication (2FA)
Why 2FA?Adds an extra layer of security even if passwords are compromised.
Implementation Options: - TOTP (Time-based One-Time Password) - Google Authenticator, Authy - SMS - Less secure but user-friendly - Email - Good balance - Hardware tokens - Most secureTOTP Implementation:const speakeasy = require('speakeasy');// Generate secret
const secret = speakeasy.generateSecret({
name: `YourApp (\${user.email})`
});
// Verify token
const verified = speakeasy.totp.verify({
secret: user.twoFactorSecret,
encoding: 'base32',
token: userProvidedToken,
window: 2
});
5. Password Requirements
Balanced ApproachDon't Over-Complicate: - Minimum 8-12 characters - Mix of letters, numbers, symbols - Avoid overly complex rulesBetter Approach: - Use password strength meters - Encourage passphrases - Check against common password lists - Implement password history (prevent reuse)6. OAuth and Social Login
When to Use: - Faster user onboarding - Reduced password management burden - Leverage established securityImplementation: - Use established libraries (Passport.js, etc.) - Verify tokens properly - Handle errors gracefully - Don't skip server-side validation7. Account Recovery
Secure Password ResetBest Practices: - Use time-limited tokens (15-30 minutes) - Single-use tokens - Send reset links via email (not SMS) - Log all reset attempts - Require email verificationImplementation:// Generate reset token
const resetToken = crypto.randomBytes(32).toString('hex');
const resetExpiry = Date.now() + 30 * 60 * 1000; // 30 minutesawait db.users.update({
resetToken: hashToken(resetToken),
resetExpiry
}, { where: { email } });
// Send email with reset link
await sendEmail(email, `/reset-password?token=\${resetToken}`);
Common Vulnerabilities to Avoid
1. SQL Injection
Prevention: - Use parameterized queries - ORM with built-in protection - Input validation2. Cross-Site Scripting (XSS)
Prevention: - Sanitize user input - Use Content Security Policy (CSP) - HttpOnly cookies3. Cross-Site Request Forgery (CSRF)
Prevention: - CSRF tokens - SameSite cookie attribute - Verify origin headers4. Session Fixation
Prevention: - Regenerate session ID on login - Invalidate old sessions5. Timing Attacks
Prevention: - Constant-time comparison functions - Don't reveal if user existsSecurity Checklist
- [ ] Passwords hashed with bcrypt/Argon2 - [ ] Secure session management - [ ] Rate limiting implemented - [ ] HTTPS everywhere - [ ] 2FA available - [ ] Secure password reset - [ ] Input validation - [ ] SQL injection prevention - [ ] XSS protection - [ ] CSRF protection - [ ] Security headers (CSP, HSTS, etc.) - [ ] Regular security audits - [ ] Logging and monitoring - [ ] Error messages don't leak information
Conclusion
Building secure authentication requires attention to detail and defense in depth. No single measure is sufficient, but together they create a robust security posture. Always stay updated with security best practices and conduct regular security audits.
*Need help securing your authentication system? [Schedule a consultation](/schedule-appointment) with our security experts.*