Security
This guide covers security best practices for deploying and using Auth in production.
Authentication
Client Keys
Always use UUID4 for client keys:
import uuid
# Good: Cryptographically random UUID4
client_key = str(uuid.uuid4())
# Bad: Predictable keys
client_key = "my-app-key" # ✗ Never do this
Store keys securely:
# Use environment variables
export AUTH_CLIENT_KEY=$(uuidgen)
# Never hardcode in source
client_key = "abc-123-def" # ✗ Insecure
Rotate keys regularly:
# Generate new key
NEW_KEY=$(uuidgen)
# Update environment
export AUTH_CLIENT_KEY=$NEW_KEY
# Restart application
JWT Configuration
Use strong secret keys:
# Generate secure key (minimum 32 characters)
openssl rand -base64 32
# Set environment variable
export AUTH_JWT_SECRET_KEY="<generated-key>"
Configure appropriate token expiration:
# Short-lived access tokens
export AUTH_JWT_ACCESS_TOKEN_EXPIRE_MINUTES=15
# Longer refresh tokens
export AUTH_JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
Encryption
Field-Level Encryption
Enable encryption for sensitive data:
# Generate encryption key
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# Enable encryption
export AUTH_ENABLE_ENCRYPTION=true
export AUTH_ENCRYPTION_KEY="<generated-key>"
What gets encrypted:
User identifiers in memberships
Permission names
Role descriptions (optional)
Key storage:
# Development: .env file (gitignored)
echo "AUTH_ENCRYPTION_KEY=..." >> .env
# Production: Secrets manager
# AWS Secrets Manager
# HashiCorp Vault
# Kubernetes Secrets
Transport Security
Always use HTTPS in production:
server {
listen 443 ssl http2;
server_name auth.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# Modern TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:5000;
proxy_set_header X-Forwarded-Proto https;
}
}
Database Security
PostgreSQL Hardening
Use strong passwords:
-- Create user with strong password
CREATE USER authuser WITH PASSWORD 'veryStr0ng&SecureP@ssw0rd!';
-- Grant minimal privileges
GRANT CONNECT ON DATABASE authdb TO authuser;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO authuser;
Connection security:
# Use SSL connections
export AUTH_POSTGRESQL_URL="postgresql://authuser:password@localhost:5432/authdb?sslmode=require"
Network isolation:
# pg_hba.conf - Allow only from application server
host authdb authuser 10.0.1.0/24 scram-sha-256
SQLite Permissions
# Restrict file permissions
chmod 600 ~/.auth.sqlite3
# Set ownership
chown authapp:authapp ~/.auth.sqlite3
Input Validation
SQL Injection Protection
Auth uses SQLAlchemy ORM, which protects against SQL injection:
# Safe: Parameterized query (ORM)
auth.add_role(user_input) # ✓ Automatically sanitized
# Unsafe: Raw SQL (not used in Auth)
db.execute(f"INSERT INTO roles VALUES ('{user_input}')") # ✗ Vulnerable
Input Sanitization
All inputs are validated:
from auth.sanitizer import sanitize_input
# Sanitization happens automatically
role_name = sanitize_input(user_provided_role)
Validation rules:
Maximum length limits
Alphanumeric + allowed special characters only
No SQL keywords
No script tags
CORS Configuration
Development
# Allow all origins (development only)
export AUTH_ALLOW_CORS=true
export AUTH_CORS_ORIGINS="*"
Production
# Restrict to specific origins
export AUTH_ALLOW_CORS=true
export AUTH_CORS_ORIGINS="https://app.example.com,https://admin.example.com"
Example configuration:
from flask_cors import CORS
# Specific origins only
CORS(app, resources={
r"/api/*": {
"origins": [
"https://app.example.com",
"https://admin.example.com"
],
"methods": ["GET", "POST", "DELETE"],
"allow_headers": ["Content-Type", "Authorization"]
}
})
Audit Logging
Enable Comprehensive Logging
export AUTH_ENABLE_AUDIT_LOGGING=true
Logged events:
Role creation/deletion
Permission grants/revocations
Membership changes
Permission checks (optional)
Monitor Audit Logs
from auth.audit import query_audit_logs
# Monitor suspicious activity
recent_logs = query_audit_logs(
action='delete',
hours=24
)
for log in recent_logs:
if log['entity_type'] == 'role':
alert_security_team(log)
Secrets Management
Development
Use .env files (gitignored):
# .env
AUTH_JWT_SECRET_KEY=dev-secret-key
AUTH_ENCRYPTION_KEY=dev-encryption-key
AUTH_POSTGRESQL_URL=postgresql://user:pass@localhost/authdb
Never commit secrets:
# .gitignore
.env
.env.local
.env.production
*.key
secrets/
Production
AWS Secrets Manager:
import boto3
import json
def get_secret(secret_name):
client = boto3.client('secretsmanager')
response = client.get_secret_value(SecretId=secret_name)
return json.loads(response['SecretString'])
secrets = get_secret('auth/production')
os.environ['AUTH_JWT_SECRET_KEY'] = secrets['jwt_key']
os.environ['AUTH_ENCRYPTION_KEY'] = secrets['encryption_key']
HashiCorp Vault:
import hvac
client = hvac.Client(url='https://vault.example.com')
client.auth.approle.login(role_id='...', secret_id='...')
secrets = client.secrets.kv.v2.read_secret_version(path='auth/config')
os.environ['AUTH_JWT_SECRET_KEY'] = secrets['data']['data']['jwt_key']
Kubernetes Secrets:
apiVersion: v1
kind: Secret
metadata:
name: auth-secrets
type: Opaque
data:
jwt-secret: <base64-encoded>
encryption-key: <base64-encoded>
db-password: <base64-encoded>
Security Headers
Add security headers to responses:
from flask import Flask
app = Flask(__name__)
@app.after_request
def set_security_headers(response):
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-XSS-Protection'] = '1; mode=block'
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
response.headers['Content-Security-Policy'] = "default-src 'self'"
return response
Rate Limiting
Nginx Rate Limiting
limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=10r/s;
server {
location /api/ {
limit_req zone=auth_limit burst=20 nodelay;
limit_req_status 429;
proxy_pass http://localhost:5000;
}
}
Application-Level Rate Limiting
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["100 per hour", "10 per minute"]
)
@app.route('/api/role/<role>', methods=['POST'])
@limiter.limit("5 per minute")
def create_role(role):
# Rate limited to 5 requests per minute
pass
Security Checklist
Pre-Production
[ ] Generate strong JWT secret key (32+ characters)
[ ] Enable encryption with Fernet key
[ ] Configure PostgreSQL with strong password
[ ] Set up SSL/TLS certificates
[ ] Configure CORS with specific origins
[ ] Enable audit logging
[ ] Set up secrets management
[ ] Disable debug mode
[ ] Configure rate limiting
[ ] Set security headers
[ ] Review and minimize permissions
[ ] Test authentication flows
[ ] Set up monitoring and alerting
Production Monitoring
[ ] Monitor failed authentication attempts
[ ] Alert on unusual permission grants
[ ] Track role/permission changes
[ ] Monitor database connections
[ ] Set up log aggregation
[ ] Configure automated backups
[ ] Test disaster recovery
[ ] Regular security audits
[ ] Key rotation schedule
[ ] Dependency updates
Incident Response
Security Breach Response
Immediate Actions:
# Rotate all keys immediately export AUTH_JWT_SECRET_KEY=$(openssl rand -base64 32) export AUTH_ENCRYPTION_KEY=$(python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())") # Restart services systemctl restart auth-server
Investigation:
# Query audit logs from auth.audit import query_audit_logs # Find suspicious activity logs = query_audit_logs(hours=24) suspicious = [log for log in logs if is_suspicious(log)]
Remediation:
Revoke compromised permissions
Reset affected user roles
Update security configurations
Notify affected users
Regular Security Tasks
Weekly
Review audit logs
Check for failed auth attempts
Monitor system resources
Monthly
Rotate encryption keys
Update dependencies
Review user permissions
Backup verification
Quarterly
Security audit
Penetration testing
Access review
Update documentation
Next Steps
Encryption - Encryption details
Audit Logging - Audit logging
Deployment - Secure deployment
Production Guide - Production hardening