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 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
|
# URLs
|
||||||
ADMIN_URL=https://admin.photos.yourdomain.com
|
ADMIN_URL=https://admin.photos.yourdomain.com
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- NODE_ENV=development
|
- NODE_ENV=development
|
||||||
- PORT=3000
|
- PORT=3000
|
||||||
- JWT_SECRET=local-dev-secret-key-123
|
- JWT_SECRET=b375996f704bb1541ad9297e7710a215fce0b59ecf1c43236aeea32ec01e7b27
|
||||||
- ADMIN_URL=http://localhost:3005
|
- ADMIN_URL=http://localhost:3005
|
||||||
- FRONTEND_URL=http://localhost:3005
|
- FRONTEND_URL=http://localhost:3005
|
||||||
# Email - uses Mailhog
|
# Email - uses Mailhog
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- NODE_ENV=development
|
- NODE_ENV=development
|
||||||
- PORT=3000
|
- PORT=3000
|
||||||
- JWT_SECRET=dev-secret-key
|
- JWT_SECRET=b55e4b3e9f212e1d1836c2ee2ec5ac47672350acdf1391c894d3433646579ad0
|
||||||
- ADMIN_URL=http://localhost:3001
|
- ADMIN_URL=http://localhost:3001
|
||||||
- FRONTEND_URL=http://localhost:3005
|
- FRONTEND_URL=http://localhost:3005
|
||||||
- SMTP_HOST=mailhog
|
- 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