Skip to content
Back to skills

Auth Patterns

ASecurity

This skill should be used when the user asks to "implement authentication", "set up JWT auth", "configure OAuth2", "implement RBAC", "add MFA/two-factor", "secure session management", or mentions "authentication", "authorization", "JWT", "OAuth", "login", "session management", "password hashing", "RBAC", "role-based access", "MFA", "two-factor", "API keys", "token refresh", "CSRF", "CORS with auth". Provides authentication and authorization patterns including JWT, OAuth2, session management, ...

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 26, 2026
securityjavascriptgojavagitapibackendsecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add iwritec0de/app-dev --skill auth-patterns --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Auth Patterns?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Auth Patterns
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/iwritec0de-auth-patterns/badge)](https://www.skillsdirectory.com/skills/iwritec0de-auth-patterns)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: auth-patterns
description: >-
  This skill should be used when the user asks to "implement authentication",
  "set up JWT auth", "configure OAuth2", "implement RBAC", "add MFA/two-factor",
  "secure session management", or mentions "authentication", "authorization",
  "JWT", "OAuth", "login", "session management", "password hashing", "RBAC",
  "role-based access", "MFA", "two-factor", "API keys", "token refresh", "CSRF",
  "CORS with auth". Provides authentication and authorization patterns including
  JWT, OAuth2, session management, RBAC, MFA, and password security.
license: MIT
metadata:
  author: Chris Kelley (hello@iwritecode.io)
  version: 1.0.0
---

# Authentication & Authorization Patterns

## JWT Authentication

### Token Structure
```
Header.Payload.Signature

Header:  { "alg": "RS256", "typ": "JWT" }
Payload: { "sub": "user-123", "iss": "myapp", "aud": "myapp-api", "exp": 1700000000, "iat": 1699999000 }
Signature: RS256(header + "." + payload, privateKey)
```

### Access + Refresh Token Pattern

```
Login → Access Token (15 min) + Refresh Token (30 days)
         │                        │
         ├── Use for API calls    ├── Use to get new access token
         ├── Short-lived          ├── Long-lived
         ├── Stateless            ├── Stored in DB (revocable)
         └── In httpOnly cookie   └── In httpOnly cookie (separate)
```

### Implementation Checklist

| Check | Details |
|-------|---------|
| Algorithm | Use RS256 for multi-service, HS256 for single service |
| Secret/Key | ≥256 bits, stored in env var, rotatable |
| Expiration | Access: 15-60 min. Refresh: 7-30 days |
| Storage | httpOnly + secure + sameSite cookies |
| Validation | Verify signature, exp, iss, aud on every request |
| Refresh | Rotate refresh token on use (invalidate old one) |
| Revocation | Store revoked tokens or use token version in DB |
| Logout | Invalidate refresh token, clear cookies |

### Token Storage Comparison

| Method | XSS Safe | CSRF Safe | Recommendation |
|--------|----------|-----------|----------------|
| httpOnly cookie | Yes | Need SameSite/token | **Recommended** |
| localStorage | No | Yes | Never for auth tokens |
| sessionStorage | No | Yes | Never for auth tokens |
| Memory (variable) | Yes | Yes | OK for SPAs (lost on refresh) |

## Password Security

### Hashing

```javascript
// CORRECT — bcrypt with sufficient rounds
import bcrypt from 'bcrypt';
const hash = await bcrypt.hash(password, 12);
const valid = await bcrypt.compare(password, hash);

// CORRECT — argon2 (preferred for new projects)
import argon2 from 'argon2';
const hash = await argon2.hash(password);
const valid = await argon2.verify(hash, password);

// NEVER — these are NOT for password hashing
// MD5, SHA-1, SHA-256 (even with salt)
```

### Password Policy

| Rule | Minimum |
|------|---------|
| Length | 8 characters (NIST recommends up to 64) |
| Complexity | Don't require special chars (NIST 2024). Check against breached password lists instead. |
| History | Prevent reuse of last 5 passwords |
| Rotation | Don't force periodic changes (NIST) |
| Breach check | Check against HaveIBeenPwned API |

## OAuth 2.0

### Flow Selection

| Client Type | Flow | Use Case |
|-------------|------|----------|
| Server-side web app | Authorization Code | Traditional web apps |
| SPA / Mobile | Authorization Code + PKCE | Public clients |
| Server-to-server | Client Credentials | Backend services |
| CLI / IoT | Device Code | No browser available |

### Authorization Code + PKCE (SPA)

```
1. Generate code_verifier (random 43-128 chars)
2. Generate code_challenge = SHA256(code_verifier)
3. Redirect to auth server with code_challenge
4. User authenticates, gets authorization code
5. Exchange code + code_verifier for tokens
6. Auth server verifies SHA256(code_verifier) == code_challenge
```

## Session Management

### Secure Session Configuration

```javascript
app.use(session({
  secret: process.env.SESSION_SECRET,  // Strong random secret
  name: '__session',                    // Custom name (not 'connect.sid')
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,     // Not accessible via JavaScript
    secure: true,       // HTTPS only
    sameSite: 'lax',    // CSRF protection
    maxAge: 3600000,    // 1 hour
    domain: '.example.com'
  }
}));
```

### Session Lifecycle

| Event | Action |
|-------|--------|
| Login | Regenerate session ID |
| Privilege change | Regenerate session ID |
| Logout | Destroy session |
| Idle timeout | Expire after 30 min inactivity |
| Absolute timeout | Expire after 8 hours regardless |

## RBAC (Role-Based Access Control)

### Simple Roles

```javascript
const ROLES = {
  admin:  ['read', 'write', 'delete', 'manage_users'],
  editor: ['read', 'write'],
  viewer: ['read'],
};

function authorize(...requiredPermissions) {
  return (req, res, next) => {
    const userPerms = ROLES[req.user.role] || [];
    const hasAll = requiredPermissions.every(p => userPerms.includes(p));
    if (!hasAll) return res.status(403).json({ error: 'Forbidden' });
    next();
  };
}

// Usage
app.delete('/api/users/:id', authorize('delete', 'manage_users'), deleteUser);
```

### Resource-Level Authorization

```javascript
// Always verify ownership
app.get('/api/posts/:id', async (req, res) => {
  const post = await db.posts.findById(req.params.id);
  if (!post) return res.status(404).json({ error: 'Not found' });

  // Check ownership OR admin role
  if (post.authorId !== req.user.id && req.user.role !== 'admin') {
    return res.status(403).json({ error: 'Forbidden' });
  }

  res.json(post);
});
```

## MFA (Multi-Factor Authentication)

### TOTP (Time-based One-Time Password)

```
1. Generate secret: base32-encoded random bytes
2. Create QR code with otpauth:// URI
3. User scans with authenticator app
4. On login: verify 6-digit code against secret + time
5. Store backup codes (hashed) for recovery
```

### Implementation Notes

- Generate 8-10 backup codes on MFA setup
- Hash backup codes in DB (like passwords)
- Mark backup codes as used (single-use)
- Allow MFA recovery via email verification
- Rate limit TOTP verification (prevent brute-force)

## Rate Limiting

### Auth-Specific Limits

| Endpoint | Limit | Window | Action on Exceed |
|----------|-------|--------|-----------------|
| POST /login | 10 | 15 min | Lock account 15 min |
| POST /register | 5 | 1 hour | Block IP |
| POST /forgot-password | 3 | 1 hour | Silently ignore |
| POST /verify-mfa | 5 | 5 min | Lock account |

## CSRF Protection

### SameSite Cookies (Primary)
```
Set-Cookie: session=abc; SameSite=Lax; Secure; HttpOnly
```

### CSRF Tokens (Additional Layer)
```
1. Server generates random token, stores in session
2. Token included in form as hidden field or meta tag
3. Server validates token matches session on POST/PUT/DELETE
```

### Double Submit Cookie Pattern
```
1. Set CSRF token in a regular cookie (readable by JS)
2. Client reads cookie, sends as X-CSRF-Token header
3. Server compares cookie value with header value
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…