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 = {
    '&': '&',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };
  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

  1. Strong authentication
  2. Input validation & sanitization
  3. Use HTTPS
  4. Configure CORS properly
  5. Implement rate limiting
  6. Prevent SQL injection
  7. Prevent XSS
  8. CSRF protection
  9. Security headers
  10. Keep dependencies updated
  11. Proper error handling
  12. 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! 🔒