# Security Guide

This document outlines the security measures and best practices for Deathwatch Roller.

## Authentication

### Session Management

- Sessions use HTTP-only cookies
- Sessions expire after inactivity
- Passwords are hashed with bcrypt
- XSS protection headers enabled

### Session Configuration

```javascript
// Example session config
session: {
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
  }
}
```

## Database Security

### Password Hashing

```typescript
// Password hashing
import bcrypt from 'bcrypt';

const hashedPassword = await bcrypt.hash(password, 12);
const isMatch = await bcrypt.compare(inputPassword, hashedPassword);
```

### Prepared Statements

All database queries use parameterized statements to prevent SQL injection:

```typescript
// ✅ GOOD - Using parameterized query
const player = await Player.findOne({
  where: { email: email },
  raw: true
});

// ❌ BAD - String concatenation
const badQuery = `SELECT * FROM players WHERE email = '${email}'`;
```

## Input Validation

### Request Validation

All API requests are validated:

```typescript
import { body, validationResult } from 'express-validator';

router.post('/players', [
  body('name').isLength({ min: 1, max: 50 }).trim(),
  body('email').isEmail().normalizeEmail(),
  body('xp').isInt({ min: 0 })
], async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }
  // Process request
});
```

## CORS Configuration

```typescript
// CORS setup
import cors from 'cors';

app.use(cors({
  origin: process.env.ALLOWED_ORIGINS?.split(','),
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));
```

## Rate Limiting

```typescript
// Rate limiter
import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP, please try again later.'
});

app.use('/api/', limiter);
```

## Security Headers

```typescript
import helmet from 'helmet';

app.use(helmet());

// Custom 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');
  next();
});
```

## Environment Variables

Store sensitive data in environment variables:

```bash
# .env file
SESSION_SECRET=your-secure-random-string
X_GM_SECRET=your-gm-secret-key
DATABASE_PASSWORD=your-database-password
```

Never commit `.env` files:

```bash
# .gitignore
.env
.env.*
!/.env.example
```

## API Security

### GM Authentication

GM endpoints require special authentication:

```typescript
// GM secret header
app.use('/api/players/gm/*', (req, res, next) => {
  const secret = req.headers['x-gm-secret'];
  if (!secret || secret !== process.env.X_GM_SECRET) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  next();
});
```

### API Rate Limits

```typescript
const apiLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 minute
  max: 100,
  keyGenerator: (req) => req.ip
});

app.use('/api/', apiLimiter);
```

## File Upload Security

```typescript
import multer from 'multer';

const upload = multer({
  storage: multer.diskStorage({
    destination: (req, file, cb) => cb(null, 'uploads/'),
    filename: (req, file, cb) => {
      const uniqueName = `${Date.now()}-${Math.random()}-${file.originalname}`;
      cb(null, uniqueName);
    }
  }),
  fileFilter: (req, file, cb) => {
    const allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (allowedTypes.includes(file.mimetype)) {
      cb(null, true);
    } else {
      cb(new Error('Invalid file type'));
    }
  },
  limits: {
    fileSize: 10 * 1024 * 1024 // 10MB
  }
});
```

## Database Backups

```bash
# Backup script
#!/bin/bash
mysqldump -u user -p database > backup_$(date +%Y%m%d_%H%M%S).sql
# Rotate old backups
find . -name "backup_*.sql" -mtime +30 -delete
```

## Monitoring

Set up monitoring for security events:

```typescript
// Audit logging
import auditlog from 'express-auditlog';

app.use(auditlog());
```

## Security Checklist

- [ ] Session cookies are HTTP-only
- [ ] Passwords are hashed with bcrypt
- [ ] SQL queries use parameterized statements
- [ ] CORS is properly configured
- [ ] Rate limiting is enabled
- [ ] Security headers are set
- [ ] Environment variables are not committed
- [ ] Input is validated on all endpoints
- [ ] File uploads are sanitized
- [ ] Dependencies are up to date

## Common Vulnerabilities

### SQL Injection Prevention

```typescript
// ✅ SAFE
User.findOne({ where: { email: email } });

// ❌ UNSAFE
User.findAll({ where: `email = '${email}'` });
```

### XSS Prevention

```typescript
// ✅ SAFE - Sanitize user input
const displayName = sanitize(userInput);

// ❌ UNSAFE - Direct output
res.send(userInput);
```

## Dependencies

Keep dependencies updated:

```bash
# Check for updates
npm outdated

# Update all
npm update

# Update specific package
npm update express
```

## Security Audits

```bash
# Run security audit
npm audit

# Fix vulnerabilities
npm audit fix
```

## Best Practices

1. **Principle of Least Privilege**: Use minimal permissions
2. **Defense in Depth**: Multiple security layers
3. **Fail Securely**: Default to safe responses
4. **Log Security Events**: Monitor for suspicious activity
5. **Regular Audits**: Periodic security reviews
