feat(security): merge Phase 4b security hardening

Complete security hardening implementation including HTTPS enforcement,
security headers, rate limiting, and comprehensive security test suite.

Key features:
- HTTPS enforcement with HSTS support
- Security headers (CSP, X-Frame-Options, X-Content-Type-Options)
- Rate limiting for all critical endpoints
- Enhanced email template security
- 87% test coverage with security-specific tests

Architect approval: 9.5/10

Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 18:28:50 -07:00
parent 115e733604
commit d3c3e8dc6b
23 changed files with 3762 additions and 7 deletions

View File

@@ -374,4 +374,102 @@ if not validate_redirect_uri(redirect_uri):
2. **Dependency Injection**: Pass dependencies, don't hard-code them
3. **Composition over Inheritance**: Prefer composition for code reuse
4. **Fail Fast**: Validate input early and fail with clear errors
5. **Explicit over Implicit**: Clear interfaces over magic behavior
5. **Explicit over Implicit**: Clear interfaces over magic behavior
## Security Practices
### Secure Logging Guidelines
#### Never Log Sensitive Data
The following must NEVER appear in logs:
- Full tokens (authorization codes, access tokens, refresh tokens)
- Passwords or secrets
- Full authorization codes
- Private keys or certificates
- Personally identifiable information (PII) beyond user identifiers (email addresses, IP addresses in most cases)
#### Safe Logging Practices
When logging security-relevant events, follow these practices:
1. **Token Prefixes**: When token identification is necessary, log only the first 8 characters with ellipsis:
```python
logger.info("Token validated", extra={
"token_prefix": token[:8] + "..." if len(token) > 8 else "***",
"client_id": client_id
})
```
2. **Request Context**: Log security events with context:
```python
logger.warning("Authorization failed", extra={
"client_id": client_id,
"error": error_code # Use error codes, not full messages
})
```
3. **Security Events to Log**:
- Failed authentication attempts
- Token validation failures
- Rate limit violations
- Input validation failures
- HTTPS redirect actions
- Client registration events
4. **Use Structured Logging**: Include metadata as structured fields:
```python
logger.info("Client registered", extra={
"event": "client.registered",
"client_id": client_id,
"registration_method": "self_service",
"timestamp": datetime.utcnow().isoformat()
})
```
5. **Sanitize User Input**: Always sanitize user-provided data before logging:
```python
def sanitize_for_logging(value: str, max_length: int = 100) -> str:
"""Sanitize user input for safe logging."""
# Remove control characters
value = "".join(ch for ch in value if ch.isprintable())
# Truncate if too long
if len(value) > max_length:
value = value[:max_length] + "..."
return value
```
#### Security Audit Logging
For security-critical operations, use a dedicated audit logger:
```python
audit_logger = logging.getLogger("security.audit")
# Log security-critical events
audit_logger.info("Token issued", extra={
"event": "token.issued",
"client_id": client_id,
"scope": scope,
"expires_in": expires_in
})
```
#### Testing Logging Security
Include tests that verify sensitive data doesn't leak into logs:
```python
def test_no_token_in_logs(caplog):
"""Verify tokens are not logged in full."""
token = "sensitive_token_abc123xyz789"
# Perform operation that logs token
validate_token(token)
# Check logs don't contain full token
for record in caplog.records:
assert token not in record.getMessage()
# But prefix might be present
assert token[:8] in record.getMessage() or "***" in record.getMessage()
```