agentleFS
iwritec0deiwritec0de/app-dev/skills/auth-patterns/SKILL.md

auth-patterns

Skill3 starsChanged 7 months agoMITView on GitHub

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.

  • Reads credentials

6 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Files
SKILL.md

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

CheckDetails
AlgorithmUse RS256 for multi-service, HS256 for single service
Secret/Key≥256 bits, stored in env var, rotatable
ExpirationAccess: 15-60 min. Refresh: 7-30 days
StoragehttpOnly + secure + sameSite cookies
ValidationVerify signature, exp, iss, aud on every request
RefreshRotate refresh token on use (invalidate old one)
RevocationStore revoked tokens or use token version in DB
LogoutInvalidate refresh token, clear cookies

Token Storage Comparison

MethodXSS SafeCSRF SafeRecommendation
httpOnly cookieYesNeed SameSite/tokenRecommended
localStorageNoYesNever for auth tokens
sessionStorageNoYesNever for auth tokens
Memory (variable)YesYesOK for SPAs (lost on refresh)

Password Security

Hashing

// 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

RuleMinimum
Length8 characters (NIST recommends up to 64)
ComplexityDon't require special chars (NIST 2024). Check against breached password lists instead.
HistoryPrevent reuse of last 5 passwords
RotationDon't force periodic changes (NIST)
Breach checkCheck against HaveIBeenPwned API

OAuth 2.0

Flow Selection

Client TypeFlowUse Case
Server-side web appAuthorization CodeTraditional web apps
SPA / MobileAuthorization Code + PKCEPublic clients
Server-to-serverClient CredentialsBackend services
CLI / IoTDevice CodeNo 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

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

EventAction
LoginRegenerate session ID
Privilege changeRegenerate session ID
LogoutDestroy session
Idle timeoutExpire after 30 min inactivity
Absolute timeoutExpire after 8 hours regardless

RBAC (Role-Based Access Control)

Simple Roles

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

// 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

EndpointLimitWindowAction on Exceed
POST /login1015 minLock account 15 min
POST /register51 hourBlock IP
POST /forgot-password31 hourSilently ignore
POST /verify-mfa55 minLock 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

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.