We need to make canvas-server more secure
-
Review the current auth implementation in ./src/api/auth and ./src/api/routes, ./src/api/middleware/workspace-acl.js with the 3 supported auth strategies - JWT(user+pass), API Token, IMAP - for security best prectices
-
Implement toggable email address validation on user registration for non-IMAP accounts using a simple email + link
- This requires a dedicated smtp configration in server/config/smtp.json, defaults to sendmail
- Draft/idea server/config/auth.json
- local enabled: bool, default true requireEmailVerification: bool, default false
- We'll need to harden the register and login pages in the canvas-web submodule
Current Security Issues:
- JWT Secret: Hardcoded default secret in production code
- Password Policy: No complexity requirements
- Email Verification: Not implemented for local accounts
- Rate Limiting: No rate limiting on auth endpoints
- Input Validation: Some endpoints lack proper validation
- Error Messages: Some error messages may leak information
- Minimum Length: 8 characters (configurable)
- Complexity Requirements:
- Uppercase letters (A-Z)
- Lowercase letters (a-z)
- Numbers (0-9)
- Special characters (!@#$%^&*()_+-=[]{};:,./<>?)
- Weak Password Detection: Blocks common weak passwords
- Maximum Length: 128 characters
- Secure Secret Generation: Uses crypto.randomBytes(64) for JWT secrets
- Token Expiration: Configurable expiration (default: 7 days)
- Token Versioning: Includes user version for invalidation on data changes
- Secret Validation: Warns about insecure default secrets
- Secure Generation: Uses crypto.randomBytes(24) for token values
- SHA-256 Hashing: Tokens are stored as SHA-256 hashes
- Expiration Support: Configurable token expiration
- Prefix Identification: API tokens use "canvas-" prefix
- Configuration: Enable/disable via
server/config/auth.json - User Status: Pending users cannot log in until verified
- Token Expiration: 48-hour expiration for verification tokens
- Email Templates: Configurable HTML and text templates
- Flexible Setup: Supports custom SMTP or system sendmail
- Fallback Support: Automatic fallback to system SMTP
- Template Variables: Support for dynamic content in emails
- Max Attempts: 5 attempts per 15 minutes (configurable)
- Lockout Duration: 30 minutes after max attempts
- Max Attempts: 3 attempts per hour (configurable)
- Prevents Abuse: Protects against automated registration
- Max Attempts: 3 attempts per hour (configurable)
- Prevents Abuse: Protects against email bombing
- Token Management: 10 operations per 5 minutes (configurable)
- Password Changes: 10 operations per 5 minutes (configurable)
- Prevents Abuse: Protects against token enumeration
- Email Verification: 5 attempts per 5 minutes (configurable)
- Password Reset: 5 attempts per 5 minutes (configurable)
- Token Verification: 5 attempts per 5 minutes (configurable)
- Profile Access: 60 requests per minute (configurable)
- Prevents Abuse: Protects against profile scraping
- Format Validation: RFC-compliant email format checking (ReDoS-safe)
- Sanitization: Automatic lowercase conversion and trimming
- Domain Validation: IMAP domain-specific validation
- Security: Uses safe regex patterns to prevent ReDoS attacks
- Format: 3-24 characters, lowercase letters, numbers, underscores, hyphens, dots
- Reserved Names: Blocks system-reserved usernames
- Pattern Matching: Strict regex validation
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- X-XSS-Protection: 1; mode=block
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: Restricts geolocation, microphone, camera
- Content-Security-Policy: Comprehensive CSP rules
- HSTS: HTTP Strict Transport Security (production only)
- Generic Messages: Login errors don't reveal user existence
- Sanitized Errors: No sensitive data in error responses
- Logging: Secure logging without sensitive data exposure
{
"strategies": {
"local": {
"enabled": true,
"requireEmailVerification": false,
"passwordPolicy": {
"minLength": 12,
"requireUppercase": true,
"requireLowercase": true,
"requireNumbers": true,
"requireSpecialChars": true,
"maxLength": 128
},
"rateLimiting": {
"loginAttempts": {
"maxAttempts": 5,
"windowMs": 900000,
"lockoutDuration": 1800000
},
"registration": {
"maxAttempts": 3,
"windowMs": 3600000
},
"passwordReset": {
"maxAttempts": 3,
"windowMs": 3600000
},
"apiOperations": {
"maxAttempts": 10,
"windowMs": 300000
},
"tokenOperations": {
"maxAttempts": 5,
"windowMs": 300000
},
"userProfile": {
"maxAttempts": 30,
"windowMs": 60000
}
}
}
},
"jwt": {
"secret": "your-secure-jwt-secret-here",
"expiresIn": "1d"
}
}{
"enabled": true,
"host": "smtp.example.com",
"port": 587,
"secure": true,
"auth": {
"user": "your-email@example.com",
"pass": "your-password"
},
"from": {
"name": "Canvas Server",
"email": "noreply@example.com"
}
}