api-pagination
Implement correct, fast API pagination — cursor vs offset trade-offs, opaque cursor encoding, stable sort keys, page-size limits, total-count costs, and…
Implement authentication securely — authentication vs authorization, password hashing (argon2id/bcrypt), sessions vs JWT (storage, expiry, refresh, revocation), MFA, OAuth2/OIDC flows, and defenses against credential stuffing, session fixation, and CSRF. Worked examples + a
$ npx -y skills add vanara-agents/skills --skill secure-auth --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/secure-authContext preview
The summary Claude sees to decide when to auto-load this skill.
Implement authentication securely — authentication vs authorization, password hashing (argon2id/bcrypt), sessions vs JWT (storage, expiry, refresh, revocation), MFA, OAuth2/OIDC flows, and defenses against credential stuffing, session fixation, and CSRF. Worked examples + a
name: secure-auth description: Implement authentication securely — authentication vs authorization, password hashing (argon2id/bcrypt), sessions vs JWT (storage, expiry, refresh, revocation), MFA, OAuth2/OIDC flows, and defenses against credential stuffing, session fixation, and CSRF. Worked examples + a runnable password-policy check. type: skill version: 2.0.0 updated: 2026-06-29
Authentication is the front door to your system, and it is the single control attackers probe hardest. The goal of this skill is **not** to teach you to invent a clever scheme — it is to help you assemble well-understood primitives correctly, because almost every real-world breach in this area comes from a broken assembly of good parts, not from cracked cryptography. Heavy detail lives in `references/`; copy-paste material in `examples/`; a runnable policy check in `scripts/`.
Three distinct questions get muddled constantly. Keep them separate:
| Question | Concern | Wrong answer looks like | |---|---|---| | Who are you? | **Authentication** (login, password, MFA) | trusting a client-supplied `user_id` | | What may you do? | **Authorization** (roles, ownership, scopes) | checking auth but not ownership (IDOR) | | How do we remember you? | **Session management** (cookies/tokens) | long-lived tokens you can't revoke |
A request can be perfectly *authenticated* and still be an attack if you skip *authorization*. The most common API vulnerability — Broken Object Level Authorization — is exactly this: a logged-in user reads `/accounts/124` when they only own `124`'s neighbor. Always check ownership server-side, never trust an identifier the client could change.
The non-negotiable rule: **never store a recoverable password.** Store a one-way hash produced by a *deliberately slow* algorithm so that a stolen database is expensive to crack offline.
import argon2 from 'argon2';
// Registration / password change — argon2id is the current default recommendation.
const hash = await argon2.hash(password, { type: argon2.argon2id });
// Store `hash` (it embeds the salt + cost params). NEVER store `password`.
// Login — constant-time verify; argon2 reads cost params from the stored hash.
const ok = await argon2.verify(hash, attempt);Use **argon2id** (preferred) or **bcrypt** (battle-tested, fine if argon2 isn't available). Never use fast general-purpose hashes (`MD5`, `SHA-256`) — a GPU computes billions of those per second, so a leak becomes a mass account takeover within hours. Always salt (argon2/bcrypt do this for you), and validate the password against a policy and a breached-password list *before* hashing — run `scripts/check-password-policy.mjs --selftest` to see the kind of check that belongs at this boundary. The full parameter-tuning guidance is in [references/password-hashing.md](references/password-hashing.md).
Two dominant models, with a real trade-off around **revocation**:
lives server-side (DB/Redis). Revocation is trivial: delete the row. This is the safe default for classic web apps.
**cannot un-issue a signed token** before it expires. Mitigate with short-lived access tokens (5–15 min) plus a revocable, rotating refresh token kept server-side.
Set-Cookie: session=9f2c...; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
Storage matters enormously: a token in `localStorage` is readable by any XSS payload, so prefer `HttpOnly` cookies (which JavaScript cannot read) over web storage for anything that authenticates a request. The complete comparison — expiry, refresh rotation, reuse detection, and revocation strategies — is in [references/sessions-vs-jwt.md](references/sessions-vs-jwt.md).
A password alone is a single point of failure against phishing and credential stuffing. Offer a second factor and require it for sensitive actions (password change, payouts):
Treat MFA as *step-up*: don't force it on every request, escalate it when risk rises.
When you offload login to a provider (Google, an identity platform), use **OAuth2 Authorization Code flow with PKCE** for web and mobile/SPA clients. Do not use the implicit flow (deprecated) and never the resource-owner password flow for third-party login. OIDC layers an identity `id_token` on top of OAuth2's access token. Validate the `id_token` signature, `iss`, `aud`, and `exp`, and use the `state` parameter to defend against CSRF on the callback. See [references/oauth2-oidc.md](references/oauth2-oidc.md) for the full flow diagrams and validation checklist, and `examples/auth-flow.md` for an annotated walk-through.
Recovery flows are a favorite bypass — they are authentication's back door. Make reset tokens **single-use, time-limited (e.g. 15–30 min), and high-entropy**, store only their hash, and invalidate all active sessions on a successful reset. Critically, return the **same response** whether or not the email exists, and keep timing uniform, so the endpoint can't be used to enumerate accounts.
🐒 Free agents, skills & packs for Claude Code One subscription. An army of Claude Code agents. 30 production-grade agents, skills, and packs for Claude Code — free, Apache-2.0, install with one command.
Repo: vanara-agents/skills
Implement correct, fast API pagination — cursor vs offset trade-offs, opaque cursor encoding, stable sort keys, page-size limits, total-count costs, and…
Deep reference for caching — what to cache, cache-aside vs read/write-through/write-behind, TTLs with jitter, eviction (LRU/LFU/FIFO), invalidation, and…
Write Conventional Commits — the type(scope)!: subject + body + footer spec — so history is readable and changelogs and SemVer bumps can be derived…
How to write safe, reversible, zero-downtime database schema migrations — additive-first changes, the expand/migrate/contract pattern, batched backfills,…
How to handle errors explicitly and consistently across an app — validate at boundaries, classify operational vs programmer errors, add context while…
Run git collaboration that scales — trunk-based vs git-flow decided by deploy cadence, branch protection and required checks, PR sizing and review etiquette,…