Skill: wpank/auth-patterns (version 1.0.0)

--- name: auth-patterns model: standard description: Authentication and authorization patterns — JWT, OAuth 2.0, sessions, RBAC/ABAC, password security, MFA, and vulnerability prevention. Use when implementing login flows, protecting routes, managing tokens, or auditing auth security. --- # Auth Patterns — Authentication & Authorization > **SECURITY-CRITICAL SKILL** — Auth is the front door. Get it wrong and nothing else matters. ## Authentication Methods | Method | How It Works | Best For | |--------|-------------|----------| | **JWT** | Signed token sent with each request | SPAs, microservices, mobile APIs | | **Session-based** | Server stores session, client holds cookie | Traditional web apps, SSR | | **OAuth 2.0** | Delegated auth via authorization server | "Login with Google/GitHub", API access | | **API Keys** | Static key sent in header | Internal services, public APIs | | **Magic Links** | One-time login link via email | Low-friction onboarding, B2C | | **Passkeys/WebAuthn** | Hardware/biometric challenge-response | High-security apps, passwordless | --- ## JWT Patterns ### Dual-Token Strategy Short-lived access token + long-lived refresh token: ``` Client → POST /auth/login → Server Client ← { access_token, refresh_token } Client → GET /api/data (Authorization: Bearer <access>) → Server Client ← 401 Expired Client → POST /auth/refresh { refresh_token } → Server Client ← { new_access_token, rotated_refresh_token } ``` ### Token Structure ```json { "header": { "alg": "RS256", "typ": "JWT", "kid": "key-2024-01" }, "payload": { "sub": "user_abc123", "iss": "https://auth.example.com", "aud": "https://api.example.com", "exp": 1700000900, "iat": 1700000000, "jti": "unique-token-id", "roles": ["user"], "scope": "read:profile write:profile" } } ``` ### Signing Algorithms | Algorithm | Type | When to Use | |-----------|------|-------------| | **RS256** | Asymmetric (RSA) | Microservices — only auth server holds private key | | **ES256** | Asymmetric (ECDSA) | Same as RS256, smaller keys and signatures | | **HS256** | Symmetric | Single-server apps — all verifiers share secret | Prefer RS256/ES256 in distributed systems. ### Token Storage | Storage | XSS Safe | CSRF Safe | Recommendation | |---------|----------|-----------|----------------| | **httpOnly cookie** | Yes | No (add CSRF token) | **Best for web apps** | | **localStorage** | No | Yes | Avoid — XSS exposes tokens | | **In-memory** | Yes | Yes | Good for SPAs, lost on refresh | ``` Set-Cookie: access_token=eyJ...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=900 ``` ### Expiration Strategy | Token | Lifetime | Rotation | |-------|----------|----------| | **Access token** | 5–15 minutes | Issued on refresh | | **Refresh token** | 7–30 days | Rotate on every use | | **ID token** | Match access token | Not refreshed | --- ## OAuth 2.0 Flows | Flow | Client Type | When to Use | |------|-------------|-------------| | **Authorization Code + PKCE** | Public (SPA, mobile) | **Default for all public clients** | | **Authorization Code** | Confidential (server) | Server-rendered web apps with backend | | **Client Credentials** | Machine-to-machine | Service-to-service, cron jobs | | **Device Code** | Input-constrained | Smart TVs, IoT, CLI on headless servers | > **Implicit flow is deprecated.** Always use Authorization Code + PKCE for public clients. ### PKCE Flow ``` 1. Client generates code_verifier (random 43-128 chars) 2. Client computes code_challenge = BASE64URL(SHA256(code_verifier)) 3. Redirect to /authorize?code_challenge=...&code_challenge_method=S256 4. User authenticates, server redirects back with authorization code 5. Client exchanges code + code_verifier for tokens at /token 6. Server verifies SHA256(code_verifier) == code_challenge ``` --- ## Session Management ### Server-Side Sessions ``` Client Cookie: session_id=a1b2c3d4 (opaque, random, no user data) Server Store: { "a1b2c3d4": { userId: 123, roles: ["admin"], expiresAt: ... } } ``` | Store | Speed | When to Use | |-------|-------|-------------| | **Redis** | Fast | Production default — TTL support, horizontal scaling | | **PostgreSQL** | Moderate | When Redis is overkill, need audit trail | | **In-memory** | Fastest | Development only | ### Session Security | Threat | Prevention | |--------|------------| | Session fixation | Regenerate session ID after login | | Session hijacking | httpOnly + Secure cookies, bind to IP/user-agent | | CSRF | SameSite cookies + CSRF tokens | | Idle timeout | Expire after 15–30 min inactivity | | Absolute timeout | Force re-auth after 8–24 hours | --- ## Authorization Patterns | Pattern | Granularity | When to Use | |---------|-------------|-------------| | **RBAC** | Coarse (admin, editor, viewer) | Most apps — simple role hierarchy | | **ABAC** | Fine (attributes: dept, time, location) | Enterprise — context-dependent access | | **Permission-based** | Medium (post:create, user:delete) | APIs — decouple permissions from roles | | **Policy-based (OPA/Cedar)** | Fine | Microservices — externalized, auditable rules | | **ReBAC** | Fine (owner, member, shared-with) | Social apps, Google Drive-style sharing | ### RBAC Implementation ```typescript const ROLE_PERMISSIONS: Record<string, string[]> = { admin: ["user:read", "user:write", "user:delete", "post:read", "post:write", "post:delete"], editor: ["user:read", "post:read", "post:write"], viewer: ["user:read", "post:read"], }; function requirePermission(permission: string) { return (req: Request, res: Response, next: NextFunction) => { const permissions = ROLE_PERMISSIONS[req.user.role] ?? []; if (!permissions.includes(permission)) { return res.status(403).json({ error: "Forbidden" }); } next(); }; } app.delete("/api/users/:id", requirePermission("user:delete"), deleteUser); ``` --- ## Password Security | Algorithm | Recommended | Memory-Hard | Notes | |-----------|------------|-------------|-------| | **Argon2id** | **First choice** | Yes | Resists GPU/ASIC attacks | | **bcrypt** | Yes | No | Battle-tested, 72-byte limit | | **scrypt** | Yes | Yes | Good alternative | | **PBKDF2** | Acceptable | No | NIST approved, weaker vs GPU | | **SHA-256/MD5** | **Never** | No | Not password hashing | **NIST 800-63B:** Favor length (12+ chars) over complexity rules. Check against breached password lists. Don't force periodic rotation unless breach suspected. --- ## Multi-Factor Authentication | Factor | Security | Notes | |--------|----------|-------| | **TOTP (Authenticator app)** | High | Offline-capable, Google Authenticator / Authy | | **WebAuthn/Passkeys** | Highest | Phishing-resistant, hardware-backed | | **SMS OTP** | Medium | Vulnerable to SIM swap — avoid for high-security | | **Hardware keys (FIDO2)** | Highest | YubiKey — best for admin accounts | | **Backup codes** | Low (fallback) | One-time use, generate 10, store hashed | --- ## Security Headers | Header | Value | |--------|-------| | **Strict-Transport-Security** | `max-age=63072000; includeSubDomains; preload` | | **Content-Security-Policy** | Restrict script sources, no inline scripts | | **X-Content-Type-Options** | `nosniff` | | **X-Frame-Options** | `DENY` | | **Referrer-Policy** | `strict-origin-when-cross-origin` | | **CORS** | Whitelist specific origins, never `*` with credentials | --- ## Common Vulnerabilities | # | Vulnerability | Prevention | |---|--------------|------------| | 1 | Broken authentication | MFA, strong password policy, breach detection | | 2 | Session fixation | Regenerate session ID on login | | 3 | JWT `alg:none` attack | Reject `none`, validate `alg` against allowlist | | 4 | JWT secret brute force | Use RS256/ES256, strong secrets (256+ bits) | | 5 | CSRF | SameSite cookies, CSRF tokens | | 6 | Credential stuffing | Rate limiting, breached password check, MFA | | 7 | Insecure password storage | Argon2id/bcrypt, never encrypt (hash instead) | | 8 | Insecure password reset | Signed time-limited tokens, invalidate after use | | 9 | Open redirect | Validate redirect URIs against allowlist | | 10 | Token leakage in URL | Send tokens in headers or httpOnly cookies only | | 11 | Privilege escalation | Server-side role checks on every request | | 12 | OAuth redirect_uri mismatch | Exact match redirect URI validation, no wildcards | | 13 | Timing attacks | Constant-time comparison for secrets | --- ## NEVER Do | # | Rule | Why | |---|------|-----| | 1 | **NEVER store passwords in plaintext or reversible encryption** | One breach exposes every user | | 2 | **NEVER put tokens in URLs or query parameters** | Logged by servers, proxies, referrer headers | | 3 | **NEVER use `alg: none` or allow algorithm switching in JWTs** | Attacker forges tokens | | 4 | **NEVER trust client-side role/permission claims** | Users can modify any client-side value | | 5 | **NEVER use MD5, SHA-1, or plain SHA-256 for password hashing** | No salt, no work factor — cracked in seconds | | 6 | **NEVER skip HTTPS in production** | Tokens and credentials sent in cleartext | | 7 | **NEVER log tokens, passwords, or secrets** | Logs are broadly accessible and retained | | 8 | **NEVER use long-lived tokens without rotation** | A single leak grants indefinite access | | 9 | **NEVER implement your own crypto** | Use established libraries — jose, bcrypt, passport | | 10 | **NEVER return different errors for "user not found" vs "wrong password"** | Enables user enumeration |

path: README.md
content: # Auth Patterns — Authentication & Authorization

Authentication and authorization patterns — JWT, OAuth 2.0, sessions, RBAC/ABAC, password security, MFA, and vulnerability prevention. Use when implementing login flows, protecting routes, managing tokens, or auditing auth security.

## What's Inside

- Authentication Methods — JWT, session-based, OAuth 2.0, API keys, magic links, passkeys/WebAuthn
- JWT Patterns — dual-token strategy, token structure, signing algorithms, storage, expiration
- OAuth 2.0 Flows — Authorization Code + PKCE, Client Credentials, Device Code
- Session Management — server-side sessions, session security, Redis/PostgreSQL stores
- Authorization Patterns — RBAC, ABAC, permission-based, policy-based (OPA/Cedar), ReBAC
- Password Security — Argon2id, bcrypt, scrypt, NIST 800-63B guidelines
- Multi-Factor Authentication — TOTP, WebAuthn/Passkeys, hardware keys, backup codes
- Security Headers — HSTS, CSP, CORS, X-Frame-Options
- Common Vulnerabilities — 13 vulnerability patterns with prevention strategies

## When to Use

- Implementing login flows and authentication
- Protecting API routes and managing tokens
- Choosing between JWT, sessions, and OAuth 2.0
- Implementing role-based or attribute-based access control
- Auditing auth security and preventing vulnerabilities
- Adding MFA to an application

## Installation

```bash
npx add https://github.com/wpank/ai/tree/main/skills/api/auth-patterns
```

### Manual Installation

#### Cursor (per-project)

From your project root:

```bash
mkdir -p .cursor/skills
cp -r ~/.ai-skills/skills/api/auth-patterns .cursor/skills/auth-patterns
```

#### Cursor (global)

```bash
mkdir -p ~/.cursor/skills
cp -r ~/.ai-skills/skills/api/auth-patterns ~/.cursor/skills/auth-patterns
```

#### Claude Code (per-project)

From your project root:

```bash
mkdir -p .claude/skills
cp -r ~/.ai-skills/skills/api/auth-patterns .claude/skills/auth-patterns
```

#### Claude Code (global)

```bash
mkdir -p ~/.claude/skills
cp -r ~/.ai-skills/skills/api/auth-patterns ~/.claude/skills/auth-patterns
```

## Related Skills

- `api-design` — API design principles including authentication requirements
- `error-handling` — Error types and HTTP error responses
- `rate-limiting` — Protecting auth endpoints from brute force

---

Part of the [API](..) skill category.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)