14 KiB
Authentication & Authorization Security Checklist
Comprehensive checklist for implementing secure authentication and authorization patterns with Better Auth and multi-tenant architecture.
Pre-Implementation Planning
- Choose authentication method (Better Auth, custom, OAuth only)
- Define user roles (admin, user, viewer, etc.)
- Map permissions to roles
- Choose session strategy (JWT, database sessions, cookies)
- Plan multi-tenant isolation (tenant-level permissions)
- Review compliance requirements (GDPR, HIPAA, SOC2)
Better Auth Setup
Installation & Configuration
- Better Auth installed (
npm install better-auth) - Configuration file created (
auth.config.tsor similar) - Database adapter configured (Drizzle, Prisma, etc.)
- Environment variables set (secrets, URLs)
- CSRF protection enabled (default in Better Auth)
OAuth Providers
-
OAuth providers configured (Google, GitHub, etc.):
providers: [ google({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET! }), github({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! }) ] -
OAuth redirect URIs whitelisted in provider dashboards
-
OAuth scopes minimal (only request what's needed)
-
OAuth state parameter validated (CSRF protection)
-
OAuth error handling implemented
Email/Password Authentication
-
Password hashing with secure algorithm (bcrypt, Argon2)
-
Password requirements enforced:
- Minimum 8 characters
- Mix of uppercase, lowercase, numbers, symbols
- Password strength meter on frontend
- Common password blocklist
-
Email verification implemented:
- Verification email sent on registration
- Token expires after reasonable time (24 hours)
- User cannot access protected routes until verified
- Resend verification email option
-
Password reset flow:
- Reset link sent to email
- Token single-use and time-limited
- Old password invalidated after reset
- User notified of password change
Session Management
Session Storage
-
Sessions stored securely:
- Database sessions (recommended for multi-tenant)
- Encrypted session cookies
- No sensitive data in localStorage
-
Session expiration configured:
- Reasonable timeout (30 minutes idle, 24 hours absolute)
- Refresh token flow (if using JWT)
- Grace period for session extension
-
Session invalidation on:
- Logout
- Password change
- Security event (suspicious activity)
- User deletion
Session Security
- httpOnly cookies (JavaScript cannot access)
- secure flag set (HTTPS only)
- sameSite attribute configured (Strict or Lax)
- Session fixation prevented (regenerate session ID on login)
- Concurrent session management (limit sessions per user)
Multi-Tenant Authentication
Tenant Context
-
Tenant identified during authentication:
- From subdomain (
tenant.example.com) - From custom domain (
example.com) - From user selection (post-login)
- From invitation link
- From subdomain (
-
tenant_id stored in session
-
User-tenant relationship verified on each request
-
Tenant switching requires re-authentication (or explicit action)
-
Cross-tenant access blocked at authentication layer
Organization Roles
-
Organization model defined (one tenant = one org)
-
User-Organization membership table created
-
Roles per organization:
- Owner (full control)
- Admin (manage users, cannot delete org)
- Member (standard access)
- Viewer (read-only)
-
Role inheritance (Owner has all Admin permissions)
-
Role assignment restricted (only Owner/Admin can assign roles)
Invitation System
-
Invitation flow implemented:
- Admin generates invitation link
- Link includes tenant_id + role
- Link expires after set time
- Link single-use or limited-use
- Email sent with invitation
-
Invitation acceptance creates user-tenant relationship
-
Invitation revocation possible before acceptance
-
Pending invitations tracked in database
Authorization Patterns
Role-Based Access Control (RBAC)
-
Roles defined at application level
-
Permissions mapped to roles
-
Permission checks in:
- API route handlers
- Repository methods (data access layer)
- UI components (hide/disable unauthorized actions)
-
Authorization middleware created:
function requireRole(role: Role) { return async (req, res, next) => { const user = req.user; if (!user || user.role !== role) { return res.status(403).json({ error: 'Forbidden' }); } next(); }; }
Attribute-Based Access Control (ABAC)
- User attributes checked (tenant_id, role, team_id)
- Resource attributes checked (owner_id, tenant_id, visibility)
- Context attributes checked (time, IP, device)
- Policy evaluation centralized (authorization service)
Row-Level Security (RLS)
-
RLS policies enabled on multi-tenant tables:
CREATE POLICY tenant_isolation ON users USING (tenant_id = current_setting('app.tenant_id')::uuid); -
tenant_id set in database context for each request
-
Admin bypass policy (when needed):
CREATE POLICY admin_all_access ON users USING ( current_setting('app.user_role') = 'admin' OR tenant_id = current_setting('app.tenant_id')::uuid ); -
RLS tested (cannot access other tenant's data)
API Security
Authentication Endpoints
-
Rate limiting on auth endpoints:
- Login: 5 attempts per 15 minutes
- Registration: 3 accounts per hour per IP
- Password reset: 3 requests per hour per email
-
Brute force protection:
- Account lockout after failed attempts
- CAPTCHA after 3 failed attempts
- Delay responses on failure (same time as success)
-
Account enumeration prevented:
- Same response for existing/non-existing users
- Generic error messages ("Invalid credentials")
Protected Endpoints
- Authentication required (middleware on all protected routes)
- Authorization verified (role/permission checks)
- tenant_id validated (user belongs to tenant)
- Input validation (Zod/Pydantic on all inputs)
- CORS configured (whitelist allowed origins)
Token Security
-
JWT tokens (if used):
- Short expiration (15 minutes for access token)
- Signed with secret key (HS256 or RS256)
- Claims validated (iss, aud, exp)
- Refresh token rotation
- Refresh token revocation on logout
-
API keys (if used):
- Stored hashed in database
- Scoped to specific tenant
- Can be revoked
- Expiration date set
- Usage tracked (rate limits per key)
Frontend Security
Client-Side Auth
-
Auth state managed (React context, store)
-
Protected routes implemented:
function ProtectedRoute({ children }) { const { user, loading } = useAuth(); if (loading) return <Loading />; if (!user) return <Navigate to="/login" />; return children; } -
Role-based UI (hide/disable unauthorized actions)
-
Token refresh handled automatically
-
Logout on 401 responses
Secure Storage
-
No sensitive data in localStorage:
- No passwords
- No full credit card numbers
- No SSNs or PII
-
Session storage for temporary data only
-
Cookies for authentication tokens (httpOnly)
CSRF Protection
- CSRF tokens on state-changing requests
- SameSite cookies (Strict or Lax)
- Referer header validation (optional defense in depth)
Password Security
Password Storage
- Never store plaintext passwords
- Use bcrypt or Argon2 (not SHA-256 or MD5)
- Salt per password (automatic with bcrypt/Argon2)
- Cost factor appropriate (10-12 for bcrypt)
- Pepper used (additional application-wide secret)
Password Policies
- Minimum length 8 characters (12+ recommended)
- Complexity requirements (optional, often counterproductive)
- Password history (prevent reuse of last 5 passwords)
- Password expiration (only if required by compliance)
- Compromised password check (Have I Been Pwned API)
Social Engineering Prevention
-
Email verification required before account activation
-
Suspicious activity alerts:
- Login from new device
- Login from new location
- Password change
- Email change
- Role change
-
Security questions avoided (weak authentication)
-
2FA encouraged (optional or required)
-
Account recovery requires multiple factors (email + SMS)
Two-Factor Authentication (2FA)
-
2FA supported (TOTP, SMS, or hardware keys)
-
2FA enrollment flow:
- User scans QR code (TOTP)
- User verifies code to confirm setup
- Backup codes generated
- 2FA cannot be disabled without authentication
-
2FA enforcement (optional or required):
- Required for admins
- Optional for users
- Grace period for enrollment (7 days)
-
Backup codes provided (10 single-use codes)
-
2FA recovery flow (if device lost)
Logging & Monitoring
Authentication Events
-
Log all auth events:
- Successful logins (user, tenant, IP, timestamp)
- Failed login attempts
- Logout events
- Password changes
- Role changes
- 2FA enrollment/removal
-
Structured logging (JSON format for parsing)
-
PII handling in logs (hash or redact sensitive data)
-
Log retention policy (90 days minimum for security events)
Anomaly Detection
-
Monitor for:
- Multiple failed logins from same IP
- Login from unusual location
- Rapid API requests (potential bot)
- Privilege escalation attempts
- Mass data access (potential breach)
-
Alerts configured for suspicious activity
-
Automated responses (account lock, CAPTCHA)
-
Security team notified for critical events
Compliance & Privacy
GDPR Compliance
- Consent captured for data processing
- Privacy policy accessible
- Right to access (users can export data)
- Right to deletion (users can delete account)
- Data minimization (only collect necessary data)
- Breach notification process defined
SOC2 Requirements
- Access logging comprehensive
- Session management secure
- Encryption in transit (HTTPS) and at rest
- MFA available for privileged accounts
- Security training for developers
Testing Authentication
Unit Tests
- Password hashing tested
- Token generation/validation tested
- Permission checks tested
- Role assignment tested
- Tenant isolation tested
Integration Tests
- Login flow tested (email/password, OAuth)
- Registration flow tested
- Password reset tested
- Session expiration tested
- 2FA flow tested
Security Tests
-
Penetration testing performed
-
OWASP Top 10 vulnerabilities checked:
- Broken authentication
- SQL injection
- XSS
- CSRF
- Security misconfiguration
-
Automated security scans (SAST, DAST)
-
Dependency vulnerabilities checked (npm audit, Snyk)
Deployment Security
-
Secrets management (Doppler, AWS Secrets Manager)
-
Environment variables not committed to git
-
HTTPS enforced (redirect HTTP to HTTPS)
-
Security headers set:
- Strict-Transport-Security
- X-Content-Type-Options
- X-Frame-Options
- Content-Security-Policy
-
Database encryption at rest
-
Backup encryption
-
Secure key rotation process
Incident Response
-
Incident response plan documented
-
Security contacts defined
-
Breach notification process:
- Identify affected users
- Notify within 72 hours (GDPR)
- Invalidate all sessions
- Force password reset
- Investigate root cause
-
Post-incident review process
-
Security patches deployment process
Scoring
- 90+ items checked: Excellent - Production-ready security ✅
- 70-89 items: Good - Most security covered ⚠️
- 50-69 items: Fair - Significant security gaps 🔴
- <50 items: Poor - Not secure for production ❌
Priority Items
Address these first:
- Password security - Hashing, policies, reset flow
- Session management - Secure storage, expiration, invalidation
- Multi-tenant isolation - tenant_id in session, RLS policies
- Rate limiting - Prevent brute force attacks
- Logging - Audit trail for security events
Common Mistakes
❌ Don't:
- Store passwords in plaintext or with weak hashing
- Use long-lived tokens without refresh mechanism
- Trust client-side validation/authorization
- Share sessions across tenants
- Log passwords or tokens
- Use JWT for sessions (use database sessions for multi-tenant)
✅ Do:
- Use proven auth libraries (Better Auth, NextAuth)
- Validate sessions on every request
- Implement defense in depth (multiple security layers)
- Test authentication thoroughly
- Monitor for suspicious activity
- Rotate secrets regularly
Related Resources
- Better Auth Documentation
- OWASP Authentication Cheat Sheet
- OWASP Session Management
- authentication-patterns skill
Total Items: 150+ security checks Critical Items: Password security, Session management, Multi-tenant, Rate limiting Coverage: Better Auth, Multi-tenant, OAuth, RBAC, RLS Last Updated: 2025-11-10