OAuth 2.0 & OpenID Connect
"Sign in with Google." "Allow this app to access your calendar." These are OAuth 2.0 and OpenID Connect at work — the protocols for letting one app act on your behalf at another without giving it your password. They're widely used and widely misunderstood, starting with the most important distinction: OAuth is about authorization, OIDC adds authentication.
The Problem OAuth Solves: Delegated Access Without Sharing Passwords
Suppose a photo-printing app wants to access your Google Photos. The naive (terrible) way: you give the app your Google password. Now it can do anything as you, forever, and you can't revoke it without changing your password. OAuth 2.0 solves this: it lets you grant the app limited, revocable access to specific resources, without ever sharing your credentials. The app gets an access token scoped to just what you approved.
The Four Roles
| Role | Who | Example |
|---|---|---|
| Resource Owner | you (the user) | you, who owns the photos |
| Client | the app wanting access | the photo-printing app |
| Authorization Server | issues tokens after you consent | Google's OAuth server |
| Resource Server | holds the protected data | the Google Photos API |
OAuth Is Authorization — OIDC Adds Authentication
The Authorization Code Flow (with PKCE)
The recommended flow for web and mobile apps. The key idea: the app never sees your password, and the powerful token is exchanged through a back channel, not exposed in the browser. Step by step:
state value).code_verifier, sends its hash (code_challenge) when starting the flow, and must present the original verifier when exchanging the code. So even if an attacker intercepts the authorization code, they can't exchange it without the verifier — which never left the legitimate app. PKCE is now recommended for all clients, not just public ones.
Scopes: Least Privilege for Delegated Access
A scope is a named permission the client requests (photos.read, calendar.write, email). The consent screen shows you exactly what you're granting, and the token is limited to those scopes. This is least privilege applied to delegation: request only the scopes you actually need, and users (rightly) distrust apps asking for more than they should. Over-broad scope requests are both a security risk and a conversion killer.
Common Misconfigurations
state → CSRF on the callback. The state parameter is a random value the app sends and verifies on return; without it, an attacker can splice their own authorization code into your session (a login-CSRF). Always generate, store, and check state. (2) Loose redirect_uri validation. If the authorization server allows wildcard or unregistered redirect URIs, an attacker can redirect the code/token to a site they control. Register exact redirect URIs. (3) Using the implicit flow. The old "implicit" flow returned tokens directly in the browser URL fragment — exposed and unrevocable; it's deprecated. Use authorization code + PKCE. (4) Treating an OAuth access token as proof of identity. An access token isn't an ID token — verify the OIDC ID token's signature, issuer (iss), audience (aud), and expiry before trusting its identity claims. (5) Not verifying the ID token at all — accepting it without checking the signature/issuer lets an attacker forge identities.
Social Login: What You Gain and Give Up
"Sign in with Google/Apple/GitHub" (OIDC) means users don't create yet another password, you don't store credentials, and you inherit the provider's strong authentication (their MFA, their anti-abuse). The trade-offs: you depend on the provider (outages, account bans, policy changes cascade to your users), you share some user data with them, and you must still handle account linking (same person, multiple providers) and the case where a user loses access to their provider account. For many apps it's a net win; weigh it deliberately rather than adding every provider button reflexively.
Hands-On Exercises
Explain the difference between OAuth 2.0 and OpenID Connect in terms of authorization vs authentication, and why using a raw OAuth access token as "proof of who the user is" is a security mistake. State what OIDC adds and which token carries identity.
📄 View solutionWalk through the authorization code flow and explain why the browser only carries a short-lived code (not the token), and why the token is exchanged server-to-server. Then explain what PKCE adds and how it defeats authorization-code interception.
📄 View solutionIdentify the security problem in each: (a) the app omits the state parameter; (b) the authorization server accepts any redirect_uri under the domain; (c) the app uses the implicit flow; (d) the app trusts the ID token's claims without verifying its signature/issuer/audience. Give the fix for each.
Chapter 8 Quick Reference
- OAuth 2.0 = delegated authorization — grant an app limited, revocable access to resources without sharing your password
- Four roles: Resource Owner (you), Client (app), Authorization Server (issues tokens), Resource Server (holds data)
- OAuth = authorization; OIDC = authentication — OIDC adds an ID token (JWT) with verified identity claims; use OIDC for "Sign in with…"
- Authorization Code flow: browser carries a short-lived code; the token is exchanged server-to-server (back channel)
- PKCE — verifier/challenge so an intercepted code can't be exchanged; recommended for all clients
- Scopes = least-privilege permissions shown on the consent screen; request only what you need
- Misconfigs: missing
state(callback CSRF) · looseredirect_uri· implicit flow (deprecated) · trusting an access token as identity · unverified ID token - Social login: no passwords to store + inherit provider's MFA, but you depend on the provider & share data — weigh deliberately
- Next chapter: account recovery & verification — secure password reset, email verification, the #1 takeover vector