spb/ultra-sharp-agent-skills Public
Ultra-Sharp Agent Skills — a research-first skill-authoring system + 72 production-ready skills for AI agents.
Python 100%
1<!--2Author: Simon-Pierre Boucher3Contact: contact@spboucher.ai4-->56# Patterns — Implementing Authentication78## Contents9- Password hashing (argon2id)10- Session cookie setup11- JWT issuance and verification12- OAuth2 authorization code + PKCE13- Password reset flow14- TOTP MFA15- Gotchas1617## Password hashing (argon2id)1819```python20from argon2 import PasswordHasher21from argon2.exceptions import VerifyMismatchError2223ph = PasswordHasher() # library defaults follow current OWASP guidance2425def hash_password(password: str) -> str:26 return ph.hash(password)2728def verify_password(stored: str, candidate: str) -> bool:29 try:30 ph.verify(stored, candidate)31 except VerifyMismatchError:32 return False33 # Transparent upgrade if parameters changed since hashing34 if ph.check_needs_rehash(stored):35 return True # caller should rehash and store36 return True37```3839Fallback: `bcrypt.hashpw(pw, bcrypt.gensalt(rounds=12))` — bcrypt truncates at 72 bytes; reject longer passwords explicitly.4041## Session cookie setup4243```python44# Flask example — equivalents exist in every framework45app.config.update(46 SESSION_COOKIE_HTTPONLY=True,47 SESSION_COOKIE_SECURE=True,48 SESSION_COOKIE_SAMESITE="Lax",49 PERMANENT_SESSION_LIFETIME=timedelta(hours=12),50)5152# On every privilege change (login, MFA pass):53session.regenerate() # or: logout_user(); new session id — blocks fixation54```5556Store sessions server-side (Redis/DB) so logout and admin revocation are real.5758## JWT issuance and verification5960```python61import jwt, datetime as dt6263ACCESS_TTL = dt.timedelta(minutes=15) # short: leaked tokens age out fast64LEEWAY = 60 # seconds of clock-skew tolerance, max6566def issue(sub: str, secret: str) -> str:67 now = dt.datetime.now(dt.timezone.utc)68 return jwt.encode(69 {"sub": sub, "iat": now, "exp": now + ACCESS_TTL, "iss": "api"},70 secret, algorithm="HS256")7172def verify(token: str, secret: str) -> dict:73 # Pin the algorithm list — never accept the header's alg claim blindly74 return jwt.decode(token, secret, algorithms=["HS256"],75 issuer="api", leeway=LEEWAY)76```7778Refresh tokens: opaque random strings, stored hashed, rotated on every use; reuse of a rotated token revokes the whole family (theft signal).7980## OAuth2 authorization code + PKCE8182```python83# authlib example (FastAPI/Starlette)84oauth.register(85 name="google",86 server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",87 client_id=..., client_secret=...,88 client_kwargs={"scope": "openid email profile", "code_challenge_method": "S256"},89)90# Callback: verify state, exchange code, then check id_token claims:91# - aud == your client_id92# - email_verified is True before trusting the email93```9495## Password reset flow9697```python98def start_reset(email: str):99 user = find_user(email)100 if user:101 raw = secrets.token_urlsafe(32)102 store_reset(user.id, sha256(raw), expires=now() + timedelta(hours=1))103 send_email(email, link_with(raw))104 return "If that address exists, we sent a link." # identical either way105106def finish_reset(raw: str, new_password: str):107 row = pop_reset(sha256(raw)) # single-use: delete on read108 if row is None or row.expired():109 raise ResetInvalid # generic error, no detail110 set_password(row.user_id, hash_password(new_password))111 revoke_all_sessions(row.user_id) # kill attacker's live sessions112```113114## TOTP MFA115116```python117import pyotp118119secret = pyotp.random_base32() # store encrypted, show QR once120totp = pyotp.TOTP(secret)121ok = totp.verify(code, valid_window=1) # ±30 s window, no more122# Recovery codes: 8-10 random codes, stored hashed, single-use.123```124125## Gotchas126127- **`alg: none` / algorithm confusion** — always pin `algorithms=[...]` when decoding JWTs; never trust the token header.128- **bcrypt 72-byte truncation** — `password[:72]` collisions; validate length or pre-hash with SHA-256+base64 before bcrypt.129- **SameSite=Lax still sends cookies on top-level GET navigation** — state-changing endpoints must be POST with CSRF protection.130- **Timing side channel on login** — run the hash verify even when the user doesn't exist (hash a dummy) so response time doesn't reveal account existence.131- **JWT logout is not logout** — without a revocation list or short TTL, "logged out" tokens keep working until expiry.132- **OAuth `state` skipped** — omitting the state check re-opens CSRF on the callback; PKCE does not replace it for web apps.133- **Storing TOTP secrets in plaintext** — encrypt at rest; a DB dump otherwise defeats MFA entirely.134