The landscape
- OAuth 2.1 / OIDC - delegated auth. User proves identity to IdP, your app gets an assertion.
- Passkeys / WebAuthn - passwordless, phishing-resistant via public-key crypto.
- JWTs - token format for carrying claims. Building block, not a protocol.
- Session cookies - the classic. Still solid.
OAuth 2.1
Consolidates 2.0 best practices.
Changes from 2.0:
- Auth Code + PKCE mandatory for all clients. Implicit flow gone.
- Refresh token rotation - one-time use.
- No password grant.
Common mistakes
- Open redirect via redirect_uri. Register exact URIs. No wildcards.
- Missing state parameter. Prevents CSRF. Generate random, validate on callback.
- Token leakage via referrer. Set
Referrer-Policy: no-referrer. - Tokens in localStorage. Accessible to XSS. Use
HttpOnlycookies or BFF pattern.
Passkeys
- Registration: Device generates key pair. Public key to server. Private key stays on device.
- Authentication: Server sends challenge. Device signs it. Server verifies.
Why it matters:
- Phishing-resistant. Credential bound to origin.
- No password reuse. Each credential unique per site.
- Nothing useful to breach. Server only stores public keys.
Considerations: Support passwords during transition. Plan for account recovery (backup codes, trusted contacts).
JWTs
Signed JSON: header.payload.signature
Common mistakes
Algorithm confusion. If verification accepts alg from the token, attackers set alg: none or sign with your public key.
// Specify algorithm explicitly
const { payload } = await jwtVerify(token, publicKey, {
algorithms: ["RS256"],
});
No expiry. Set short expiry - minutes for access tokens.
Secrets in payload. Base64-encoded, not encrypted. Anyone can decode.
Can't revoke. Stateless by design. Need instant revocation? Short-lived tokens + server-side state.
Session cookies
Server creates session, sends session ID as cookie. Browser sends it automatically.
Flags
| Flag | Purpose |
|---|---|
HttpOnly | Not accessible via JS |
Secure | HTTPS only |
SameSite=Lax | Mitigates CSRF |
When to use
| Scenario | Recommendation |
|---|---|
| Traditional web app | Session cookies |
| SPA with same-origin API | Session cookies or BFF |
| SPA calling third-party APIs | JWT |
| Microservices | Short-lived JWT |
| Instant revocation needed | Server-side sessions |
MFA
- TOTP - Authy, Google Authenticator. Easy, widely supported.
- WebAuthn/FIDO2 - Hardware keys. Strongest, phishing-resistant.
- SMS/email - Vulnerable to SIM swapping. Fallback only.
Enforce MFA for sensitive operations, not just login. Step-up auth for high-risk actions.
The takeaway
OAuth 2.1 with PKCE for delegated auth. Passkeys for phishing-resistant login. JWTs: validate algorithm explicitly, short expiry, no secrets in payload. Session cookies still work for server-rendered apps. Layer MFA on top.
