diff --git a/.env.example b/.env.example index 0adec48..8da9d03 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,7 @@ # JWT Secret for authentication -JWT_SECRET=your-secret-key-here +# IMPORTANT: Generate a secure random secret with: openssl rand -hex 32 +# NEVER use the default value or commit the actual secret to version control +JWT_SECRET=CHANGE_ME_TO_A_64_CHARACTER_SECURE_RANDOM_STRING_GENERATED_BY_OPENSSL # URLs ADMIN_URL=https://admin.photos.yourdomain.com diff --git a/docker-compose.local.yml b/docker-compose.local.yml index 909e67c..19c57aa 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -10,7 +10,7 @@ services: environment: - NODE_ENV=development - PORT=3000 - - JWT_SECRET=local-dev-secret-key-123 + - JWT_SECRET=b375996f704bb1541ad9297e7710a215fce0b59ecf1c43236aeea32ec01e7b27 - ADMIN_URL=http://localhost:3005 - FRONTEND_URL=http://localhost:3005 # Email - uses Mailhog diff --git a/docker-compose.yml b/docker-compose.yml index edce7a0..3e5fb58 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,7 @@ services: environment: - NODE_ENV=development - PORT=3000 - - JWT_SECRET=dev-secret-key + - JWT_SECRET=b55e4b3e9f212e1d1836c2ee2ec5ac47672350acdf1391c894d3433646579ad0 - ADMIN_URL=http://localhost:3001 - FRONTEND_URL=http://localhost:3005 - SMTP_HOST=mailhog diff --git a/docs/SECURITY_BEST_PRACTICES.md b/docs/SECURITY_BEST_PRACTICES.md new file mode 100644 index 0000000..2f67d5f --- /dev/null +++ b/docs/SECURITY_BEST_PRACTICES.md @@ -0,0 +1,179 @@ +# Security Best Practices for PicPeak + +## JWT Secret Management + +### Generating Secure Secrets + +Always generate cryptographically secure random secrets for JWT signing: + +```bash +# Generate a 64-character hex string (256 bits) +openssl rand -hex 32 + +# Alternative: Generate a base64 string +openssl rand -base64 32 + +# Alternative: Using Node.js +node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" +``` + +### Environment-Specific Secrets + +**NEVER use the same JWT secret across different environments!** + +- **Development**: Use the secure secret in `docker-compose.yml` +- **Staging**: Generate a unique secret for staging +- **Production**: Generate a unique secret for production + +### Secret Requirements + +1. **Minimum Length**: 32 characters (enforced by application) +2. **Recommended Length**: 64 characters (256 bits) +3. **Character Set**: Use hex or base64 encoding +4. **Uniqueness**: Each environment must have a unique secret + +### What NOT to Do + +❌ **Never commit real secrets to version control** +```bash +# Bad - real secret in code +JWT_SECRET=my-actual-production-secret +``` + +❌ **Never use predictable or weak secrets** +```bash +# Bad examples +JWT_SECRET=secret123 +JWT_SECRET=mycompanyname +JWT_SECRET=password +JWT_SECRET=your-secret-key +``` + +❌ **Never share secrets between environments** +```bash +# Bad - same secret everywhere +DEV_JWT_SECRET=same-secret +PROD_JWT_SECRET=same-secret +``` + +### Secure Secret Storage + +#### For Local Development +- Docker Compose files can contain development secrets +- These should still be secure random values + +#### For Production +1. **Environment Variables** + ```bash + # Set via secure environment + export JWT_SECRET=$(openssl rand -hex 32) + ``` + +2. **Secret Management Services** + - AWS Secrets Manager + - HashiCorp Vault + - Azure Key Vault + - Kubernetes Secrets + +3. **CI/CD Integration** + - Store secrets in CI/CD platform's secret storage + - Never log or echo secrets in build scripts + +### Secret Rotation + +Implement a secret rotation strategy: + +1. **Regular Rotation**: Rotate secrets every 90 days +2. **Incident Response**: Rotate immediately if compromised +3. **Graceful Rotation**: Support multiple valid secrets during transition + +### Monitoring and Alerts + +1. **Startup Validation**: Application refuses to start without proper JWT_SECRET +2. **Length Warnings**: Warnings for secrets shorter than 32 characters +3. **Default Detection**: Critical error if default secret is detected + +## Additional Security Measures + +### Password Requirements +- Minimum 12 characters +- Mix of uppercase, lowercase, numbers, and special characters +- Check against common password lists +- Implement password strength meter + +### Session Security +- Implement token expiration (24 hours for admin, configurable for galleries) +- Add refresh token mechanism +- Implement token revocation +- Use secure session storage (Redis in production) + +### API Security +- Rate limiting on all endpoints +- Extra strict limits on authentication endpoints +- CSRF protection for state-changing operations +- Input validation on all user inputs + +### File Upload Security +- Validate file types by content, not just extension +- Implement virus scanning +- Limit file sizes +- Sanitize filenames +- Store files outside web root + +### Database Security +- Use parameterized queries (Knex.js handles this) +- Validate and sanitize all inputs +- Implement query timeouts +- Use least-privilege database users + +### HTTPS and Headers +- Always use HTTPS in production +- Implement security headers: + - Strict-Transport-Security + - X-Frame-Options + - X-Content-Type-Options + - Content-Security-Policy + - X-XSS-Protection + +### Logging and Monitoring +- Log authentication attempts +- Monitor for suspicious patterns +- Never log sensitive data (passwords, tokens) +- Implement audit trails for admin actions + +## Security Checklist for Deployment + +- [ ] Generate unique JWT_SECRET for environment +- [ ] Verify JWT_SECRET meets minimum requirements +- [ ] Store secrets securely (not in code) +- [ ] Enable HTTPS +- [ ] Configure security headers +- [ ] Set up rate limiting +- [ ] Enable audit logging +- [ ] Test authentication flows +- [ ] Verify file upload restrictions +- [ ] Check database query security + +## Incident Response + +If a security incident occurs: + +1. **Immediate Actions** + - Rotate all secrets + - Review access logs + - Disable compromised accounts + +2. **Investigation** + - Analyze logs for unauthorized access + - Check for data exfiltration + - Review code changes + +3. **Recovery** + - Deploy security patches + - Force password resets if needed + - Notify affected users + +4. **Prevention** + - Update security practices + - Implement additional monitoring + - Conduct security audit \ No newline at end of file diff --git a/scripts/generate-jwt-secret.sh b/scripts/generate-jwt-secret.sh new file mode 100755 index 0000000..73ba075 --- /dev/null +++ b/scripts/generate-jwt-secret.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Generate a secure JWT secret for PicPeak + +echo "===================================" +echo "JWT Secret Generator for PicPeak" +echo "===================================" +echo "" + +# Generate the secret +SECRET=$(openssl rand -hex 32) + +echo "Your new JWT secret (64 characters):" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "$SECRET" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo "To use this secret:" +echo "" +echo "1. For Docker Compose (.env file):" +echo " JWT_SECRET=$SECRET" +echo "" +echo "2. For environment variable:" +echo " export JWT_SECRET=$SECRET" +echo "" +echo "3. For systemd service:" +echo " Environment=\"JWT_SECRET=$SECRET\"" +echo "" +echo "⚠️ IMPORTANT:" +echo " - Keep this secret secure and never commit it to version control" +echo " - Use different secrets for different environments" +echo " - Store production secrets in a secure secret management system" +echo " - Rotate secrets regularly (every 90 days recommended)" +echo "" \ No newline at end of file