plugins/backend-toolkit/skills/authentication/SKILL.md
Choose and implement auth correctly — JWT vs session vs OAuth decision, pin allowed algorithms server-side, rotate refresh tokens with reuse detection, avoid the classic JWT pitfalls. Use when adding login, integrating OAuth, or when token handling looks risky. Not for access control / permissions (use authorization) or a broader OWASP audit (use backend-security-audit).
npx skillsauth add jaykim88/claude-ai-engineering authenticationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Establish who the caller is, securely. Pick the right mechanism for the use case and avoid the well-known token pitfalls (algorithm confusion, non-rotating refresh tokens, client-trusted claims).
Universal — the JWT-vs-session-vs-OAuth decision, algorithm pinning, and refresh-rotation-with-reuse-detection are auth principles independent of language; the library differs.
1b. Require MFA / step-up for sensitive operations
Pin allowed algorithms server-side — never trust the token alg header
none algorithm bypassShort access tokens + rotating refresh tokens
Store tokens safely (coordinate with frontend)
security-audit token-storage ruleValidate token claims as untrusted input
exp, iss, aud, signature — all of themdata-validation)5b. Defend the login endpoint itself
state (CSRF) + PKCE for public clients; verify the redirect URI is on the allowlist exactly (not a prefix)alg: none and an RS256→HS256 confusion token → verify both rejected| ❌ Anti-pattern | ✅ Correct |
|---|---|
| Trusting the token's alg header | Pin allowed algorithms server-side |
| Long-lived access tokens, no rotation | Short access + rotating refresh w/ reuse detection |
| Tokens in localStorage | HttpOnly + Secure + SameSite cookies |
| JWT for a simple revocable web session | Server-side session (easy revocation) |
| Skipping iss/aud/exp verification | Verify all standard claims |
| Reusing the pre-login session id post-login | Rotate session id on login (session fixation defense) |
| No login rate-limit / generic 401 only by IP | Rate-limit by IP and per account; lockout after N failures |
| User-enumeration leak ("no such user" vs "wrong password") | Generic "invalid credentials" for both |
| Tier | Examples | Action SLA |
|---|---|---|
| Critical | alg: none or RS256→HS256 accepted; refresh token never rotates; tokens in localStorage; no MFA on admin / money-moving actions | Block release; fix immediately |
| Major | Long access-token TTL with no revocation; missing aud/iss checks; no login rate-limit (credential stuffing open); session id not rotated on login (fixation) | Fix this sprint |
| Minor | Session timeout untuned; OAuth state param missing on a low-risk flow; user-enumeration leak in error messages | Schedule within 2 sprints |
algorithms list on the verifier — confirm every live issuer is already on the new algorithmfeat(auth): add <mechanism> login / fix(auth): pin allowed JWT algorithms@nestjs/passport + passport-jwt; configure algorithms: ['RS256'] explicitly (pin)fastapi-users; PyJWT with explicit algorithms=[...]golang-jwt with explicit alg pinning; avoid the historical alg-confusion footgunnone-alg and RS256→HS256 classes apply to every JWT libraryauthorization — authn (who you are) precedes authz (what you can do)backend-security-audit — token handling is a top OWASP audit areadata-validation — token claims are untrusted input — validate themalg); rotate refresh tokens with reuse detection that revokes the whole family on replay. Modern auth is more than tokens: passkeys for consumer products, MFA / step-up on sensitive actions, login-endpoint rate-limit by IP and per account (credential-stuffing rotates IPs), and session-id rotation on login (fixation).development
Design webhooks correctly on both sides — sending (HMAC signing, retries with backoff, at-least-once) and receiving (verify signature on raw body, enqueue + 200 fast, dedupe on event id). Use when adding webhook delivery or consuming a provider's webhooks. Not for internal service-to-service events (use async-messaging) or general outbound-call retry policy (use resilience-patterns).
testing
Use transactions and isolation levels correctly — keep them short, no network calls inside, explicit isolation, retry on serialization conflicts, and choose optimistic vs pessimistic locking. Use when a write spans multiple tables, when concurrent updates corrupt data, or when designing money/inventory flows. Not for cross-service event delivery (use async-messaging Outbox) or schema-level constraints (use schema-design).
development
Backend testing pyramid — unit for pure logic, integration against a real DB (Testcontainers), and consumer-driven contract testing (Pact) for service boundaries. Use before a feature, after a bug fix, or when services break each other on deploy. Not for load testing (use performance-profiling) or security testing (use backend-security-audit).
data-ai
Design a relational schema — normalize to 3NF then denormalize with justification, choose the right Postgres index type per data shape, enforce constraints at the DB. Use when modeling a new domain, when queries are slow, or before a migration. Not for diagnosing slow queries (use query-optimization) or shipping the change without downtime (use migration-strategy).