OAuth 2.1 & OpenID Connect
OAuth authorizes and OIDC (ID token) authenticates, OAuth 2.1 makes Authorization Code + PKCE mandatory and deletes implicit and password grants, you pick auth-code+PKCE for user apps, client-credentials for M2M, and device flow for TVs/CLIs, and you harden tokens with scopes, audience, state/nonce, and optionally DPoP/mTLS.
OAuth authorizes, OIDC authenticates
OAuth and OIDC are the most commonly muddled pair in interviews, so nail the distinction first. OAuth 2.0/2.1 is an authorization framework: it lets a user grant an application limited access to their resources on another service without sharing a password. The output is an access token that says "this app may call these APIs on this user's behalf." OpenID Connect (OIDC) is a thin authentication layer built on top of OAuth: it adds an ID token (a signed JWT) that proves who the user is. Shorthand: OAuth is "may this app do X," OIDC is "who is this user." "Sign in with Google" is OIDC; "let this app read your Google Drive" is OAuth.
The four roles: the resource owner (the user), the client (the app requesting access), the authorization server or AS (issues tokens, e.g. Google's identity service), and the resource server or RS (the API that accepts the token). Keep these straight and the flows make sense.
Interview nuance: saying "we use OAuth to log users in" is imprecise and interviewers notice. OAuth alone authorizes; you log users in with OIDC's ID token. And never say "we use OAuth" without naming a grant, that is the tell of someone who has not implemented it.
OAuth 2.1 removed the footguns
- Authorization Code flow with PKCE is now required for all clients, including confidential ones. PKCE (Proof Key for Code Exchange) has the client send a hashed random
code_verifierup front and reveal it at token exchange, so an intercepted authorization code is useless to an attacker who lacks the verifier. - The Implicit grant (tokens returned directly in the URL fragment) is removed. It leaked tokens in browser history and referrers.
- The Resource Owner Password Credentials grant (app collects the user's password) is removed. It defeats the entire point of delegation.
- Exact redirect-URI string matching is required, closing open-redirect and token-theft holes.
Grant selection, the thing you must get right
- Web apps, single-page apps, and mobile/native apps: Authorization Code + PKCE. SPAs and mobile are public clients (they cannot hold a secret), so PKCE is what protects them.
- Machine-to-machine (a backend service calling an API with no user present): Client Credentials grant. The service authenticates with its own client ID and secret (or mTLS) and gets a token representing itself.
- Input-constrained devices (smart TVs, CLIs, IoT): Device Authorization grant. The device shows a code and URL, the user approves on their phone, and the device polls for the token.
Grant selection is the part interviewers check. Match each client to the grant it should use.
Authorization Code + PKCE (SPA/mobile/web):
client --(auth request + code_challenge)--> AS
user authenticates & consents at AS
AS --(authorization code)--> client (via exact redirect_uri)
client --(code + code_verifier + [secret])--> AS token endpoint
AS --> access_token (+ id_token for OIDC, + refresh_token)
Hardening tokens
Security parameters: scope limits what the token can do (least privilege: request read:contacts, not full_access). audience names which RS the token is for, so a token minted for API A cannot be replayed at API B. Consent screens make the grant explicit to the user. state protects the redirect against CSRF, and OIDC's nonce plus PKCE protect against replay and the confused-deputy problem.
Bearer vs sender-constrained tokens. A bearer token is like cash: whoever holds it can use it, so a leaked bearer token is fully usable. Sender-constrained tokens bind the token to a client key so a thief cannot use it: DPoP (a per-request proof signed by a key the client holds) or mTLS-bound tokens (bound to the client's TLS certificate). High-value APIs should prefer sender-constrained tokens.
Enterprise SSO: SAML is the older XML-based standard still dominant in enterprise; OIDC is the modern JSON/JWT equivalent and is preferred for new integrations. Pair either with SCIM for automated user provisioning and deprovisioning so that when HR offboards someone, access is revoked everywhere.
Recap: OAuth authorizes and OIDC (ID token) authenticates, OAuth 2.1 makes Authorization Code + PKCE mandatory and deletes implicit and password grants, you pick auth-code+PKCE for user apps, client-credentials for M2M, and device flow for TVs/CLIs, and you harden tokens with scopes, audience, state/nonce, and optionally DPoP/mTLS.
Apply
Your turn
The task this lesson builds to.
Design 'Sign in with X' plus third-party API access for a platform, choosing the correct grant flow and token strategy.
Think about
- What is the OAuth vs OIDC distinction?
- Which grant do you pick for web/SPA/mobile vs M2M vs devices?
- What did OAuth 2.1 make mandatory or remove?
Practice
Make it stick
A second problem on the same idea, so it survives past today.
Design the OAuth architecture for a fintech platform like Plaid that connects to thousands of banks and exposes an API consumed by thousands of third-party developer apps, where you are simultaneously an OAuth client (to banks) and an OAuth provider (to your customers).
Think about
- How do the two OAuth roles (client to banks, provider to developers) differ?
- Why do sender-constrained tokens (FAPI/mTLS) matter on the bank leg?
- How does cascading revocation flow through the whole chain?