# 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.ts` or 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.):
```typescript
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
- [ ] **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:
```typescript
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:
```sql
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):
```sql
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:
```typescript
function ProtectedRoute({ children }) {
const { user, loading } = useAuth();
if (loading) return ;
if (!user) return ;
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:
1. **Password security** - Hashing, policies, reset flow
2. **Session management** - Secure storage, expiration, invalidation
3. **Multi-tenant isolation** - tenant_id in session, RLS policies
4. **Rate limiting** - Prevent brute force attacks
5. **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](https://better-auth.com)
- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
- [OWASP Session Management](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html)
- [authentication-patterns skill](../SKILL.md)
---
**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