<< All versions

Skill v1.0.0

currentAutomated scan100/100
trinhhaox/ag-kit/authentication
──Details
PublishedOctober 26, 2026 at 12:54 AM
Content Hashsha256:68da55b4f45dc1d5...
Git SHA67b559b415f1
──Files
Files (1 file, 5.5 KB)
SKILL.md5.5 KBactive
SKILL.md · 197 lines · 5.5 KB

version: "1.0.0" name: authentication description: Authentication patterns - JWT, sessions, OAuth 2.0/OIDC, passkeys, RBAC, MFA. Token rotation, password hashing, rate limiting. allowed-tools: Read, Write, Edit, Glob, Grep


Authentication Patterns

Production auth patterns covering tokens, sessions, OAuth, and access control.

Token-Based (JWT)

Token Strategy

TokenLifetimeStoragePurpose
Access token15 minMemory/cookieAPI authorization
Refresh token7 dayshttpOnly cookieToken renewal
ID token15 minMemoryUser identity (OIDC)

JWT Best Practices

typescript
// Sign with RS256 for asymmetric verification
const token = await new SignJWT({ sub: userId, role })
.setProtectedHeader({ alg: 'RS256' })
.setIssuedAt()
.setExpirationTime('15m')
.setJti(crypto.randomUUID()) // Unique token ID for revocation
.sign(privateKey);

Token Rotation

typescript
async function refreshTokens(refreshToken: string) {
const payload = await verify(refreshToken);
// Revoke old refresh token (one-time use)
await revokeToken(payload.jti);
// Issue new pair
const newAccess = await signAccessToken(payload.sub);
const newRefresh = await signRefreshToken(payload.sub);
return { accessToken: newAccess, refreshToken: newRefresh };
}

Session-Based

Setup

typescript
// httpOnly cookie - not accessible via JavaScript
Set-Cookie: session_id=abc123;
HttpOnly;
Secure;
SameSite=Lax;
Path=/;
Max-Age=86400

Session Store

  • Redis for distributed systems (TTL = session lifetime)
  • Database for audit requirements
  • Regenerate session ID on privilege change (login, role change)

OAuth 2.0 / OIDC

Authorization Code Flow (with PKCE)

1. Generate code_verifier (random 43-128 chars)
2. Derive code_challenge = BASE64URL(SHA256(code_verifier))
3. Redirect to /authorize?response_type=code&code_challenge=...&state=RANDOM
4. User authenticates at provider
5. Provider redirects back with ?code=AUTH_CODE&state=RANDOM
6. Verify state matches (CSRF prevention)
7. Exchange code + code_verifier for tokens at /token endpoint

Provider Integration

typescript
// Generic OAuth callback handler
async function handleCallback(code: string, state: string) {
verifyState(state, session.oauthState);
const tokens = await exchangeCode(code, codeVerifier);
const userInfo = await fetchUserInfo(tokens.access_token);
const user = await findOrCreateUser(userInfo);
await createSession(user.id);
}

Password Hashing

Recommended Algorithms

AlgorithmConfigUse When
Argon2idmemory=64MB, iterations=3, parallelism=4Default choice
bcryptcost ≥ 12Legacy systems, wider library support
scryptN=2^17, r=8, p=1Alternative to Argon2

Never: MD5, SHA-1, SHA-256 alone, unsalted hashes


RBAC (Role-Based Access Control)

Permission Model

typescript
type Permission = 'read' | 'write' | 'delete' | 'admin';
type Role = {
name: string;
permissions: Permission[];
inherits?: string[]; // Role inheritance
};
// Check authorization
function authorize(user: User, required: Permission): boolean {
const userPerms = resolvePermissions(user.roles);
return userPerms.includes(required) || userPerms.includes('admin');
}

Middleware Pattern

typescript
function requirePermission(...perms: Permission[]) {
return async (req, res, next) => {
const user = req.user;
if (!user || !perms.every(p => authorize(user, p))) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
}
// Usage
app.delete('/api/users/:id', requirePermission('admin', 'delete'), handler);

MFA (Multi-Factor Authentication)

TOTP (Time-Based One-Time Password)

typescript
// Setup: generate secret, show QR code
const secret = generateTOTPSecret();
const qrUrl = `otpauth://totp/App:${email}?secret=${secret}&issuer=App`;
// Verify: check 6-digit code with 30s window
function verifyTOTP(secret: string, code: string): boolean {
const expected = generateTOTP(secret, Math.floor(Date.now() / 30000));
return timingSafeEqual(code, expected);
}

Backup Codes

  • Generate 10 single-use codes at MFA setup
  • Hash and store them (like passwords)
  • Mark as used after consumption

Rate Limiting

Auth Endpoints

EndpointLimitWindowAction on Exceed
POST /login5 attempts15 minLock + email alert
POST /register3 attempts1 hourCAPTCHA
POST /forgot-password3 attempts1 hourSilent (no error leak)
POST /verify-mfa5 attempts5 minSession invalidation

Implementation

typescript
// Token bucket with Redis
async function rateLimit(key: string, limit: number, windowSec: number) {
const current = await redis.incr(key);
if (current === 1) await redis.expire(key, windowSec);
if (current > limit) throw new TooManyRequestsError();
}

Security Checklist

  • [ ] Tokens in httpOnly, Secure, SameSite cookies
  • [ ] CSRF protection (state parameter, double-submit cookie)
  • [ ] Password hashing with Argon2id or bcrypt (cost ≥ 12)
  • [ ] Rate limiting on all auth endpoints
  • [ ] Session regeneration on privilege change
  • [ ] Refresh token rotation (single-use)
  • [ ] Secrets from environment variables only
  • [ ] No sensitive data in JWT payload (use opaque tokens if needed)
  • [ ] Audit logging for login, logout, password change, MFA events
All versions