feat(security): implement secure JWT secrets for all environments
- Replace short dev secrets with secure 64-character (256-bit) secrets - Update docker-compose.yml with secure development secret - Update docker-compose.local.yml with unique secure secret - Improve .env.example with clear security instructions - Add comprehensive security best practices documentation - Create helper script to generate secure JWT secrets Security improvements: - All environments now use cryptographically secure 64-character secrets - Clear warnings and instructions prevent use of weak secrets - Documentation guides proper secret management - Helper script makes it easy to generate new secrets 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+3
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
Executable
+34
@@ -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 ""
|
||||
Reference in New Issue
Block a user