Authentication Patterns

By Davy Rogers

OAuth 2.1, passkeys, JWTs, sessions. What to use, what to avoid.

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 HttpOnly cookies or BFF pattern.

Passkeys

  1. Registration: Device generates key pair. Public key to server. Private key stays on device.
  2. 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

FlagPurpose
HttpOnlyNot accessible via JS
SecureHTTPS only
SameSite=LaxMitigates CSRF

When to use

ScenarioRecommendation
Traditional web appSession cookies
SPA with same-origin APISession cookies or BFF
SPA calling third-party APIsJWT
MicroservicesShort-lived JWT
Instant revocation neededServer-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.

Want a professional to look at it?Get an AppSec Health Check.