Password Security
Password Security
Hashing
// Use bcrypt for password hashing
const bcrypt = require('bcrypt');
// Hash password
async function hashPassword(password) {
const saltRounds = 12;
return await bcrypt.hash(password, saltRounds);
}
// Verify password
async function verifyPassword(password, hash) {
return await bcrypt.compare(password, hash);
}
// Never store plain text passwords
// Never use MD5 or SHA for passwords
Password Policies
// Minimum requirements
const passwordSchema = z.string()
.min(8, 'Password must be at least 8 characters')
.max(100, 'Password must be less than 100 characters')
.regex(/[A-Z]/, 'Password must contain at least one uppercase letter')
.regex(/[a-z]/, 'Password must contain at least one lowercase letter')
.regex(/[0-9]/, 'Password must contain at least one number')
.regex(/[^A-Za-z0-9]/, 'Password must contain at least one special character');
// Check against common passwords
const commonPasswords = ['password', '123456', 'qwerty'];
function isCommonPassword(password) {
return commonPasswords.includes(password.toLowerCase());
}
Brute Force Protection
// Rate limiting
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 attempts
message: 'Too many login attempts',
skipSuccessfulRequests: true,
});
app.post('/login', loginLimiter, async (req, res) => {
// Login logic
});
// Account lockout
const attempts = new Map();
function checkAttempts(email) {
const userAttempts = attempts.get(email) || { count: 0, lockUntil: 0 };
if (Date.now() < userAttempts.lockUntil) {
return { locked: true, remaining: userAttempts.lockUntil - Date.now() };
}
return { locked: false };
}
function recordAttempt(email, success) {
const userAttempts = attempts.get(email) || { count: 0, lockUntil: 0 };
if (success) {
attempts.delete(email);
} else {
userAttempts.count++;
if (userAttempts.count >= 5) {
userAttempts.lockUntil = Date.now() + 15 * 60 * 1000; // 15 minutes
}
attempts.set(email, userAttempts);
}
}
Session Security
Session Security
Secure Session Configuration
const session = require('express-session');
const RedisStore = require('connect-redis').default;
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000, // 24 hours
sameSite: 'strict',
},
}));
Session Management
// Regenerate session ID on login
app.post('/login', async (req, res) => {
const user = await authenticate(req.body);
if (user) {
req.session.regenerate((err) => {
req.session.userId = user.id;
res.json({ success: true });
});
}
});
// Destroy session on logout
app.post('/logout', (req, res) => {
req.session.destroy((err) => {
res.clearCookie('connect.sid');
res.json({ success: true });
});
});
// Session fixation prevention
app.use((req, res, next) => {
if (req.session.userId && !req.session.initialized) {
req.session.regenerate(() => {
req.session.initialized = true;
next();
});
} else {
next();
}
});
Session Security Headers
app.use((req, res, next) => {
// Prevent session fixation
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
// Content Security Policy
res.setHeader(
'Content-Security-Policy',
"default-src 'self'; script-src 'self';"
);
next();
});
OAuth and MFA
OAuth and MFA
OAuth 2.0 Flow
// Frontend: Redirect to OAuth provider
const authUrl = new URL('https://provider.com/oauth/authorize');
authUrl.searchParams.set('client_id', clientId);
authUrl.searchParams.set('redirect_uri', redirectUri);
authUrl.searchParams.set('response_type', 'code');
authUrl.searchParams.set('scope', 'profile email');
authUrl.searchParams.set('state', generateState());
window.location.href = authUrl.toString();
// Backend: Exchange code for token
app.get('/callback', async (req, res) => {
const { code, state } = req.query;
// Verify state
if (state !== req.session.oauthState) {
return res.status(403).json({ error: 'Invalid state' });
}
// Exchange code for token
const tokenResponse = await fetch('https://provider.com/oauth/token', {
method: 'POST',
body: JSON.stringify({
grant_type: 'authorization_code',
code,
client_id: clientId,
client_secret: clientSecret,
redirect_uri: redirectUri,
}),
});
const { access_token } = await tokenResponse.json();
// Get user info
const userResponse = await fetch('https://provider.com/userinfo', {
headers: { Authorization: `Bearer ${access_token}` },
});
const user = await userResponse.json();
// Create or login user
req.session.userId = user.id;
res.redirect('/dashboard');
});
Multi-Factor Authentication
// TOTP (Time-based One-Time Password)
const speakeasy = require('speakeasy');
// Generate secret
const secret = speakeasy.generateSecret({
name: `MyApp:${user.email}`,
});
// Store secret securely
await updateUser(user.id, { totpSecret: secret.base32 });
// Verify token
function verifyTOTP(token, secret) {
return speakeasy.totp.verify({
secret,
encoding: 'base32',
token,
window: 1, // Allow 30 seconds window
});
}
// Login with MFA
app.post('/login', async (req, res) => {
const user = await authenticate(req.body);
if (user.totpSecret) {
// Require MFA token
if (!req.body.totpToken) {
return res.json({ requiresMFA: true });
}
const valid = verifyTOTP(req.body.totpToken, user.totpSecret);
if (!valid) {
return res.status(401).json({ error: 'Invalid MFA token' });
}
}
// Login successful
req.session.userId = user.id;
res.json({ success: true });
});
Security Best Practices
- Use HTTPS everywhere
- Implement rate limiting
- Use secure session configuration
- Regenerate session IDs on login
- Implement MFA for sensitive accounts
- Use OAuth for third-party login
- Hash passwords with bcrypt
- Implement account lockout
- Log authentication events
- Use Content Security Policy
Practice Problems
Create a reusable React component implementing Authentication Security. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Authentication Security using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Authentication Security for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. Why use bcrypt for password hashing?
2. What is session fixation?
3. What is the primary purpose of Authentication Security?
4. What is a common mistake when implementing Authentication Security?
Flashcards
Question
Why hash passwords?
Click to reveal answer
Answer
To protect them if the database is compromised - hashes are irreversible.
Question
What is rate limiting?
Click to reveal answer
Answer
Limiting the number of requests to prevent brute force attacks.
Question
What is MFA?
Click to reveal answer
Answer
Multi-Factor Authentication - requiring multiple forms of verification.
Question
What is OAuth?
Click to reveal answer
Answer
An open standard for token-based authentication and authorization.
Question
What is Authentication Security?
Click to reveal answer
Answer
Authentication Security is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.Hash passwords with bcrypt, never plain text
- 2.Implement rate limiting and account lockout
- 3.Regenerate session IDs on login
- 4.Use MFA for sensitive accounts
- 5.Use secure session configuration
Interview Tips
- •Explain password hashing and why bcrypt is used
- •Discuss session fixation and how to prevent it
- •Know OAuth flow and MFA implementation
Cheat Sheet
Auth Security Cheat Sheet
Password Security
- Hash with bcrypt (salt rounds 12+)
- Never store plain text
- Implement rate limiting
- Use account lockout
Session Security
- Use secure, httpOnly cookies
- Regenerate session ID on login
- Set reasonable expiration
- Use Redis for session store
MFA
- TOTP (Time-based One-Time Password)
- Require for sensitive operations
- Store secrets securely
OAuth
- Use for third-party login
- Verify state parameter
- Exchange code for token server-side
Headers
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Content-Security-Policy