HTTPS Everywhere
SSL/TLS Configuration
nginx
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}Certificate Management
bash
# Let's Encrypt
certbot --nginx -d example.com -d www.example.com
# Auto-renewal
certbot renew --dry-runSecurity Headers
Essential Headers
javascript
// Express.js
import helmet from 'helmet';
app.use(helmet());
// Custom headers
app.use((req, res, next) => {
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
res.setHeader('Permissions-Policy', 'geolocation=(), microphone=()');
next();
});Content Security Policy
javascript
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
},
}));XSS Protection
Input Sanitization
javascript
import DOMPurify from 'dompurify';
// Sanitize HTML
const clean = DOMPurify.sanitize(dirtyInput);
// React (automatic by default)
<div>{userInput}</div> // Safe
// Dangerously set innerHTML (dangerous)
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(dirtyInput) }} />Output Encoding
javascript
// Encode output
import he from 'he';
const encoded = he.encode('<script>alert("XSS")</script>');
// <script>alert("XSS")</script>SQL Injection Prevention
Parameterized Queries
javascript
// Bad - Vulnerable
const query = `SELECT * FROM users WHERE id = '${userId}'`;
// Good - Parameterized
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);
// Best - ORM
const user = await User.findByPk(userId);ORM Protection
javascript
// Sequelize
const users = await User.findAll({
where: {
status: 'active'
}
});
// Prisma
const users = await prisma.user.findMany({
where: { status: 'active' }
});Authentication Security
Password Hashing
javascript
import bcrypt from 'bcrypt';
// Hash password
const hashedPassword = await bcrypt.hash(password, 10);
// Verify password
const isValid = await bcrypt.compare(password, hashedPassword);Session Management
javascript
// Secure cookie configuration
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // Prevent XSS
maxAge: 3600000, // 1 hour
sameSite: 'strict', // CSRF protection
}
}));JWT Security
Token Structure
javascript
import jwt from 'jsonwebtoken';
// Create token
const token = jwt.sign(
{ userId: user.id },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
);
// Verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET);Best Practices
- 1Use strong secrets: At least 32 characters
- 2Short expiration: 15 minutes to 1 hour
- 3Refresh tokens: Long-lived refresh tokens
- 4HTTPS only: Never transmit over HTTP
- 5Store securely: httpOnly cookies
CSRF Protection
CSRF Tokens
javascript
import csrf from 'csurf';
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/form', csrfProtection, (req, res) => {
// Process form
});SameSite Cookies
javascript
app.use(session({
cookie: {
sameSite: 'strict', // or 'lax'
secure: true,
}
}));Rate Limiting
Express Rate Limit
javascript
import rateLimit from 'express-rate-limit';
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per windowMs
message: 'Too many requests',
});
app.use('/api/', limiter);Data Validation
Input Validation
javascript
import { body, validationResult } from 'express-validator';
app.post('/api/users', [
body('email').isEmail().normalizeEmail(),
body('password').isLength({ min: 8 }),
body('age').isInt({ min: 18, max: 120 }),
], (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Process request
});File Upload Security
Validation
javascript
import multer from 'multer';
const upload = multer({
dest: 'uploads/',
limits: { fileSize: 5 * 1024 * 1024 }, // 5MB
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png'];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Invalid file type'));
}
}
});Dependency Security
Audit Dependencies
bash
# Check for vulnerabilities
npm audit
# Fix vulnerabilities
npm audit fix
# Automated scanning
npm install -g npm-check-updates
ncuLogging & Monitoring
Security Events
javascript
// Log security events
app.use((req, res, next) => {
if (req.body.password) {
logger.warn('Password in request', {
ip: req.ip,
path: req.path,
});
}
next();
});
// Failed login attempts
if (!isValid) {
logger.warn('Failed login attempt', {
email: req.body.email,
ip: req.ip,
});
}Best Practices Summary
- 1Always use HTTPS: No exceptions
- 2Validate all input: Never trust user input
- 3Use parameterized queries: Prevent SQL injection
- 4Implement rate limiting: Prevent brute force
- 5Keep dependencies updated: Security patches
- 6Use security headers: Extra protection layer
- 7Log security events: Monitor for attacks
- 8Regular security audits: Stay proactive
Conclusion
Web security is ongoing. Stay updated with latest threats and implement defense in depth.