skills/authentication-patterns/SKILL.md
Comprehensive authentication and authorization implementation guide. Use when the user asks about JWT tokens, OAuth 2.0 flows, session management, API key auth, SSO setup, SAML, OIDC, password hashing, multi-factor authentication, CSRF protection, token storage, CORS headers, rate limiting auth endpoints, bearer tokens, refresh tokens, OAuth scopes, identity providers, user permissions, role-based access control, attribute-based access control, or any authentication and authorization architecture, implementation, or security patterns.
npx skillsauth add 1mangesh1/dev-skills-collection authentication-patternsInstall 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.
Reference for implementing authentication in web, mobile, and API applications.
Three Base64URL-encoded parts separated by dots: header.payload.signature.
alg) and token type (typ).sub, iat, exp, iss, aud, plus custom claims.Authorization: Bearer <access_token> on each request.const jwt = require("jsonwebtoken");
const accessToken = jwt.sign({ sub: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn: "15m" });
const refreshToken = jwt.sign({ sub: user.id }, process.env.REFRESH_SECRET, { expiresIn: "7d" });
function verifyToken(req, res, next) {
const header = req.headers.authorization;
if (!header?.startsWith("Bearer ")) return res.sendStatus(401);
try { req.user = jwt.verify(header.slice(7), process.env.JWT_SECRET); next(); }
catch { return res.sendStatus(401); }
}
exp, iss, and aud on the server.alg: none or algorithm-switching attacks.For server-side apps. Client gets an authorization code via redirect and exchanges it for tokens server-side.
GET /authorize?response_type=code&client_id=...&redirect_uri=...&scope=...&state=...?code=...&state=...POST /token with grant_type=authorization_code, code, client_id, client_secret.Required for public clients (SPAs, mobile) that cannot store a client secret.
code_verifier, derive code_challenge = BASE64URL(SHA256(code_verifier)).code_challenge and code_challenge_method=S256 in the authorize request.code_verifier in the token exchange. Server verifies the hash matches.Machine-to-machine, no user. POST /token with grant_type=client_credentials, client_id, client_secret, scope. Returns an access token directly.
For input-constrained devices (smart TVs, CLI tools). Device gets a user code and verification URL, user authenticates on another device, device polls until complete.
import requests
resp = requests.post("https://auth.example.com/token", data={
"grant_type": "authorization_code", "code": auth_code,
"redirect_uri": REDIRECT_URI, "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET,
})
access_token = resp.json()["access_token"]
data = requests.get("https://api.example.com/data",
headers={"Authorization": f"Bearer {access_token}"}).json()
Set-Cookie: sid=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600
| Store | Pros | Cons | |----------|------------------------------|---------------------------------| | Memory | Zero setup | Lost on restart, single-process | | Redis | Fast, TTL support, clustered | Extra infrastructure | | Database | Durable, queryable | Slower, needs cleanup job |
crypto.randomBytes(32), secrets.token_urlsafe(32)). Prefix for identification: sk_live_....Authorization: Basic base64(username:password)
Acceptable: internal services behind VPN over TLS, development environments, webhook shared secrets. Not acceptable: public-facing APIs, anything without HTTPS, anywhere token-based auth is feasible. Always pair with rate limiting.
otpauth:// URI). Client generates a 6-digit code every 30 seconds.pyotp, speakeasy.id_token (JWT) with user claims (sub, email, name)./.well-known/openid-configuration. Verify id_token via JWKS; validate iss, aud, exp, nonce.| Algorithm | Notes | |-----------|----------------------------------------------------------| | bcrypt | Widely supported, cost factor 12+ recommended | | Argon2id | Password Hashing Competition winner, memory-hard | | scrypt | Memory-hard, good where Argon2 is unavailable |
Never use MD5, SHA-1, or SHA-256 alone -- these are fast hashes, trivially brute-forced. Never use unsalted hashes.
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))
is_valid = bcrypt.checkpw(password.encode(), hashed)
| Method | XSS Risk | CSRF Risk | Notes | |-----------------|----------|-----------|-------------------------------------------------| | httpOnly cookie | Low | Medium | Not accessible to JS; pair with SameSite + CSRF | | localStorage | High | None | Readable by any script on the page | | sessionStorage | High | None | Clears on tab close | | In-memory (JS) | Low | None | Lost on refresh; use silent refresh flow |
Recommended: refresh tokens in httpOnly Secure SameSite cookies; access tokens in memory; silent refresh on page load.
*) with Access-Control-Allow-Credentials: true.Authorization in Access-Control-Allow-Headers./login, /token, /register, /password-reset.429 Too Many Requests with Retry-After. Use exponential backoff lockouts.alg: none.redirect_uri matches a pre-registered value exactly.function requireAuth(req, res, next) {
const token = req.headers.authorization?.split(" ")[1];
if (!token) return res.status(401).json({ error: "Missing token" });
try { req.user = jwt.verify(token, process.env.JWT_SECRET); next(); }
catch { return res.status(401).json({ error: "Invalid token" }); }
}
function requireRole(...roles) {
return (req, res, next) => {
if (!roles.includes(req.user.role)) return res.status(403).json({ error: "Forbidden" });
next();
};
}
app.get("/admin", requireAuth, requireRole("admin"), adminHandler);
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
security = HTTPBearer()
async def get_current_user(creds: HTTPAuthorizationCredentials = Depends(security)):
try:
payload = jwt.decode(creds.credentials, SECRET_KEY, algorithms=["HS256"])
except jwt.InvalidTokenError:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
user = await get_user(payload["sub"])
if not user:
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
return user
@app.get("/profile")
async def profile(user=Depends(get_current_user)):
return {"id": user.id, "email": user.email}
import { NextRequest, NextResponse } from "next/server";
import { jwtVerify } from "jose";
const SECRET = new TextEncoder().encode(process.env.JWT_SECRET);
export async function middleware(request: NextRequest) {
const token = request.cookies.get("access_token")?.value;
if (!token) return NextResponse.redirect(new URL("/login", request.url));
try { await jwtVerify(token, SECRET); return NextResponse.next(); }
catch { return NextResponse.redirect(new URL("/login", request.url)); }
}
export const config = { matcher: ["/dashboard/:path*", "/api/protected/:path*"] };
tools
Parallel execution with xargs, GNU parallel, and batch processing patterns. Use when user mentions "xargs", "parallel", "batch processing", "run in parallel", "parallel execution", "process list of files", "bulk operations", "concurrent commands", "map over files", or running commands on multiple inputs.
development
WebSocket implementation for real-time bidirectional communication. Use when user mentions "websocket", "ws://", "wss://", "real-time", "live updates", "chat application", "socket.io", "Server-Sent Events", "SSE", "push notifications", "live data", "streaming data", "bidirectional communication", "websocket server", "reconnection", or building real-time features.
tools
Frontend bundler configuration for Webpack and Vite. Use when user mentions "webpack", "vite", "bundler", "vite config", "webpack config", "code splitting", "tree shaking", "hot module replacement", "HMR", "build optimization", "bundle size", "chunk splitting", "loader", "plugin", "esbuild", "rollup", "dev server", or configuring JavaScript build tools.
tools
VS Code configuration, extensions, keybindings, and workspace optimization. Use when user mentions "vscode", "vs code", "vscode settings", "vscode extensions", "keybindings", "code editor", "workspace settings", "settings.json", "launch.json", "tasks.json", "vscode snippets", "devcontainer", "remote development", or customizing their VS Code setup.