feat(security): implement comprehensive security hardening
- Add CSRF protection with cookie-based tokens - Add cookie-parser and csurf middleware - Create GET /api/csrf-token endpoint - Frontend automatically includes CSRF token in POST/PUT/DELETE requests - Add retry logic for expired CSRF tokens - Implement account lockout mechanism - Add database fields: failedLoginAttempts, lockedUntil - Track failed login attempts and lock accounts after max attempts (configurable) - Auto-unlock after lockout duration expires - Return helpful error messages with remaining time - Add comprehensive security environment variables - Rate limiting configuration (API, auth, email endpoints) - CSRF protection toggle - Password policy requirements - Account lockout settings - Logging levels - Add comprehensive test coverage - 6 new tests for account lockout functionality - 11 new tests for CSRF protection - All tests handle enabled/disabled states gracefully - Update documentation - Add Phase 3 security hardening to SESSION_CONTEXT.md - Document new database fields and migration - Update progress to 85% Files changed: - Backend: app.js, auth controller, security config, new migration - Frontend: api.js with CSRF token handling - Tests: auth.test.js (extended), csrf.test.js (new) - Config: .env examples with security variables - Docs: SESSION_CONTEXT.md updated
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const helmet = require('helmet');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const csrf = require('csurf');
|
||||
const securityConfig = require('./config/security');
|
||||
const { apiLimiter } = require('./middleware/rateLimiter');
|
||||
|
||||
@@ -53,6 +55,40 @@ app.use(cors({
|
||||
app.use(express.json({ limit: securityConfig.bodyLimit }));
|
||||
app.use(express.urlencoded({ extended: true, limit: securityConfig.bodyLimit }));
|
||||
|
||||
// Cookie parser (required for CSRF protection)
|
||||
app.use(cookieParser());
|
||||
|
||||
// CSRF Protection (Phase 3 - Security Hardening)
|
||||
if (securityConfig.csrf.enabled) {
|
||||
const csrfProtection = csrf({
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production', // HTTPS only in production
|
||||
sameSite: 'strict',
|
||||
}
|
||||
});
|
||||
|
||||
// Apply CSRF protection to all routes
|
||||
app.use(csrfProtection);
|
||||
|
||||
// CSRF token endpoint - provides token to clients
|
||||
app.get('/api/csrf-token', (req, res) => {
|
||||
res.json({ csrfToken: req.csrfToken() });
|
||||
});
|
||||
|
||||
// CSRF error handler
|
||||
app.use((err, req, res, next) => {
|
||||
if (err.code === 'EBADCSRFTOKEN') {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
error: 'Invalid CSRF token',
|
||||
message: 'Form submission failed. Please refresh the page and try again.',
|
||||
});
|
||||
}
|
||||
next(err);
|
||||
});
|
||||
}
|
||||
|
||||
// Request logging middleware
|
||||
app.use((req, res, next) => {
|
||||
console.log(`${new Date().toISOString()} - ${req.method} ${req.path}`);
|
||||
|
||||
Reference in New Issue
Block a user