Security is crucial in web development. Here are essential security practices to protect your applications.
1. Authentication & Authorization
Strong Password Policies
// Enforce strong passwords
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
// Hash passwords (never store plaintext)
const hashedPassword = await bcrypt.hash(password, 10);
JWT Best Practices
// Use short expiration times
const token = jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
// Implement refresh tokens
// Store tokens securely (httpOnly cookies)
2. Input Validation
Server-Side Validation
// Always validate on server
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
age: z.number().min(18).max(120)
});
const validated = schema.parse(req.body);
Sanitize Inputs
// Prevent XSS
const sanitized = DOMPurify.sanitize(userInput);
// Prevent SQL Injection (use parameterized queries)
db.query('SELECT * FROM users WHERE id = ?', [userId]);
3. HTTPS & SSL/TLS
// Always use HTTPS in production
// Redirect HTTP to HTTPS
// Use HSTS headers
app.use((req, res, next) => {
if (!req.secure && process.env.NODE_ENV === 'production') {
return res.redirect(`https://${req.headers.host}${req.url}`);
}
next();
});
4. CORS Configuration
// Configure CORS properly
app.use(cors({
origin: process.env.ALLOWED_ORIGINS.split(','),
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
5. Rate Limiting
// Prevent brute force attacks
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5 // limit each IP to 5 requests per windowMs
});
app.use('/api/login', limiter);
6. SQL Injection Prevention
// Always use parameterized queries
// Bad
db.query(`SELECT * FROM users WHERE email = '${email}'`);
// Good
db.query('SELECT * FROM users WHERE email = ?', [email]);
7. XSS Prevention
// Escape user input
const escapeHtml = (text) => {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, m => map[m]);
};
// Use Content Security Policy
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
"default-src 'self'; script-src 'self'");
next();
});
8. CSRF Protection
// Use CSRF tokens
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
9. Security Headers
// Set security headers
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000');
next();
});
10. Dependency Security
# Regularly update dependencies
npm audit
npm audit fix
# Use tools like Snyk, Dependabot
11. Error Handling
// Don't expose sensitive information
app.use((err, req, res, next) => {
if (process.env.NODE_ENV === 'production') {
res.status(500).json({ error: 'Internal server error' });
} else {
res.status(500).json({ error: err.message });
}
});
12. Logging & Monitoring
// Log security events
logger.warn('Failed login attempt', {
ip: req.ip,
email: req.body.email,
timestamp: new Date()
});
// Monitor for suspicious activity
Best Practices Summary
- Strong authentication
- Input validation & sanitization
- Use HTTPS
- Configure CORS properly
- Implement rate limiting
- Prevent SQL injection
- Prevent XSS
- CSRF protection
- Security headers
- Keep dependencies updated
- Proper error handling
- Monitor security events
Conclusion
Security requires:
- Defense in depth
- Regular updates
- Security audits
- Team training
- Incident response plan
Security is not optional—it’s essential! 🔒