Security Best Practices for User API
The OpenConnector User API implements comprehensive security measures to protect against various attack vectors including Cross-Site Scripting (XSS) attacks and brute force login attempts.
Overview
Our security implementation includes multiple layers of protection:
- Input Validation & Sanitization
- Rate Limiting & Brute Force Protection
- Security Headers
- Session Management
- Logging & Monitoring
Protection Against Cross-Site Scripting (XSS)
Input Sanitization
All user inputs are automatically sanitized through our SecurityService:
// Automatic sanitization of all inputs
$sanitizedData = $this->securityService->sanitizeInput($data);
Features:
- HTML entity encoding to prevent script injection
- Removal of dangerous patterns (script tags, event handlers)
- Null byte filtering
- Length limiting to prevent DoS attacks
Security Headers
Every API response includes security headers:
X-Frame-Options: DENY- Prevents clickjackingX-Content-Type-Options: nosniff- Prevents MIME sniffingX-XSS-Protection: 1; mode=block- Browser XSS protectionContent-Security-Policy- Restricts resource loadingReferrer-Policy- Controls referrer information
Content Validation
Login credentials undergo strict validation:
// Username validation
- Minimum 2 characters
- No dangerous characters (<, >, ', ', /, \)
- Maximum length limits
- Character encoding validation
// Password validation
- Maximum length limits (prevents DoS)
- No HTML encoding (preserves actual password)
Protection Against Brute Force Attacks
Multi-Layer Rate Limiting
The system implements sophisticated rate limiting:
Per-User Rate Limiting
- Limit: 5 failed attempts per 15-minute window
- Action: Progressive delays then account lockout
- Duration: 1 hour lockout after threshold
Per-IP Rate Limiting
- Limit: 5 failed attempts per 15-minute window
- Action: IP address blocking
- Duration: 1 hour lockout after threshold
Progressive Delays
- Base Delay: 2 seconds
- Escalation: Exponential backoff (2s → 4s → 8s → 16s → 32s → 60s max)
- Reset: Successful login clears delays
Account Lockout Protection
// Automatic lockout triggers
if ($userAttempts >= 5) {
// Lock account for 1 hour
$lockoutUntil = time() + 3600;
$this->cache->set($userLockoutKey, $lockoutUntil, 3600);
}
IP-based Protection
- Tracks failed attempts per IP address
- Blocks suspicious IP addresses automatically
- Considers proxy headers (X-Forwarded-For, etc.)
- Validates IP formats to prevent spoofing
Security Event Logging
All security events are logged with contextual information:
Logged Events
failed_login_attempt- Invalid credentialsrate_limit_exceeded- Too many attemptsuser_locked_out- Account temporarily disabledip_locked_out- IP address blockedsuccessful_login- Authentication succeededlogin_attempt_during_lockout- Attempt during lockout period
Log Information
{
'event': 'failed_login_attempt',
'username': 'sanitized_username',
'ip_address': '192.168.1.1',
'reason': 'invalid_credentials',
'user_attempts': 3,
'ip_attempts': 2,
'timestamp': '2024-01-15 14:30:22'
}
Implementation Details
SecurityService Features
The SecurityService class provides:
// Rate limiting check
$rateLimitCheck = $this->securityService->checkLoginRateLimit($username, $clientIp);
// Input sanitization
$sanitizedInput = $this->securityService->sanitizeInput($input);
// Credential validation
$validation = $this->securityService->validateLoginCredentials($credentials);
// Security headers
$response = $this->securityService->addSecurityHeaders($response);
// IP address detection
$clientIp = $this->securityService->getClientIpAddress($request);
Cache-based Storage
Security data is stored using NextCloud's distributed cache:
- Storage: Redis/Memcached (configurable)
- Persistence: Automatic expiration
- Scalability: Works across multiple servers
- Performance: Fast read/write operations
API Response Codes
Security-related HTTP Status Codes
400 Bad Request- Invalid input or missing credentials401 Unauthorized- Authentication failed429 Too Many Requests- Rate limit exceeded403 Forbidden- Account disabled or insufficient permissions
Response Examples
Rate Limited:
{
'error': 'Too many login attempts. Please wait before trying again.',
'retry_after': 8,
'lockout_until': null
}
Account Locked:
{
'error': 'Account temporarily locked due to too many failed login attempts',
'retry_after': null,
'lockout_until': 1705334622
}
Successful Login:
{
'message': 'Login successful',
'user': { /* user data */ },
'session_created': true
}
Configuration Options
Rate Limiting Settings
You can adjust these constants in SecurityService.php:
private const RATE_LIMIT_ATTEMPTS = 5; // Max attempts per window
private const RATE_LIMIT_WINDOW = 900; // 15 minutes in seconds
private const LOCKOUT_DURATION = 3600; // 1 hour in seconds
private const PROGRESSIVE_DELAY_BASE = 2; // Base delay in seconds
private const MAX_PROGRESSIVE_DELAY = 60; // Maximum delay in seconds
Security Headers
Customize security headers in the addSecurityHeaders() method:
// Content Security Policy
$response->addHeader('Content-Security-Policy', "default-src 'none'; frame-ancestors 'none';");
// Cache Control
$response->addHeader('Cache-Control', 'no-store, no-cache, must-revalidate, private');
Best Practices for Implementation
1. Always Use Security Service
// ✅ Correct - Use SecurityService
$response = $this->securityService->addSecurityHeaders($response);
// ❌ Incorrect - Direct response
return new JSONResponse($data);
2. Sanitize All Inputs
// ✅ Correct - Sanitize inputs
$sanitizedData = $this->securityService->sanitizeInput($data);
// ❌ Incorrect - Direct usage
$username = $_POST['username']; // Never do this
3. Validate Before Processing
// ✅ Correct - Validate first
$validation = $this->securityService->validateLoginCredentials($credentials);
if (!$validation['valid']) {
return error_response($validation['error']);
}
// ❌ Incorrect - Process without validation
$user = $this->userManager->checkPassword($username, $password);
4. Log Security Events
All authentication attempts should be logged for monitoring and analysis.
5. Use Generic Error Messages
Avoid revealing system information:
// ✅ Correct - Generic message
return new JSONResponse(['error' => 'Invalid username or password']);
// ❌ Incorrect - Reveals information
return new JSONResponse(['error' => 'User john.doe does not exist']);
Monitoring and Alerting
Key Metrics to Monitor
- Failed Login Rate - Sudden spikes may indicate attacks
- Lockout Events - High frequency suggests ongoing attacks
- IP Blocking - Geographic patterns may reveal bot networks
- Response Times - Delays may indicate DoS attempts
Log Analysis
Search for security events in logs:
# Find failed login attempts
grep 'failed_login_attempt' /var/log/nextcloud.log
# Find rate limit exceeded events
grep 'rate_limit_exceeded' /var/log/nextcloud.log
# Find lockout events
grep 'locked_out' /var/log/nextcloud.log
Additional Security Recommendations
1. Use HTTPS Only
Ensure all API endpoints are served over HTTPS to prevent credential interception.
2. Regular Security Updates
Keep NextCloud and all dependencies updated to the latest versions.
3. Strong Password Policies
Implement password complexity requirements at the application level.
4. Two-Factor Authentication
Consider implementing 2FA for additional security layers.
5. Regular Security Audits
Perform regular penetration testing and security audits.
6. Web Application Firewall
Consider using a WAF for additional protection against common attacks.
Conclusion
The OpenConnector User API implements industry-standard security practices to protect against both XSS attacks and brute force attempts. The multi-layered approach ensures comprehensive protection while maintaining usability for legitimate users.
For any security concerns or questions, please refer to the code documentation or contact the development team.