What Are You Delegating?

Every abstraction is a trade: it removes work by making decisions for you. Those decisions are still being made — just not by you, and not visibly. For each abstraction: what it genuinely handles, what remains yours, and the escape hatch.

What are you delegating to an identity provider?
Security
You write
1const session = await auth.signIn({ email, password })
The abstraction handles
  • Password hashing with a sane work factor
  • MFA, passkeys, breach-password detection
  • Rate limiting on credential endpoints
  • Session or token issuance and signing
  • Social login, SSO, the compliance paperwork
Still your responsibility
  • Authorization — the provider establishes *who*; your code still decides *what they may touch*
  • Token handling in the browserHttpOnly, Secure, SameSite, storage location, lifetime
  • Revocation — a self-contained token outlives the user's logout unless you designed for it
  • Object-level checks — the user changes an id in the URL; only your code notices
  • Which database role executes the query — a broad role means one authorization bug reaches every row
Know your escape hatch

When: You need to answer "may this principal do this to this resource" — the provider never had that information.

Drop to: Your own authorization layer: explicit checks at the resource, scoped roles, an audit trail.

Adopting a provider and assuming access control is handled is the most common serious vulnerability in web applications.

Go deeper on this one:One login, all the way down