How does OAuth 2 actually work?
OAuth 2.0 is a delegated authorisation protocol. It exists so you can let an application act on your behalf at another service without giving that application your password. It is not a login protocol, and most of the confusion around it comes from being used as one.1
The four roles
- Resource owner — you.
- Client — the application that wants access.
- Authorization server — the service that authenticates you and issues tokens.
- Resource server — the API holding the data.
Keeping these straight resolves most OAuth questions on its own, because almost every mistake is a step performed by the wrong role.
The authorisation code flow, step by step
This is the only flow worth writing today.
- The client redirects you to the authorization server with what it wants
(
scope), who it is (client_id), where to come back to (redirect_uri), a randomstate, and a PKCEcode_challenge. - You authenticate — with the authorization server, never with the client — and approve the scopes.
- You are redirected back with a short-lived authorization code.
- The client exchanges that code, server to server, for an access token,
proving it started the flow by sending the PKCE
code_verifier. - The client calls the resource server with the access token.
The reason for the two-step dance is that step 4 happens over a back channel.
The token never travels through the browser’s address bar, so it never lands in
history, logs or a Referer header.1
PKCE, and why the implicit flow died
The implicit flow returned the token directly in the redirect, in the URL. That was a workaround for browsers that could not keep a client secret, and it leaked tokens through every mechanism that records URLs.
PKCE replaces it. The client generates a random code_verifier, sends its
hash up front as the code_challenge, and presents the original when redeeming
the code. An attacker who intercepts the code cannot use it without the
verifier. PKCE is now recommended for all clients, not just mobile ones.1
state is not optional
The state parameter is a random value you send and then verify on return. It
is the CSRF defence for the flow. Omitting it lets an attacker feed you their
own authorization code, quietly connecting your session to their account.2
Where OpenID Connect fits
OAuth 2 gives an application access. It says nothing about who you are — an
access token is a bearer credential, not an identity claim. OpenID Connect
is a thin layer on top that adds an id_token: a signed JWT describing the
authenticated user. If you want “sign in with X”, you want OIDC. Using a raw
OAuth access token as proof of identity is the single most common security
mistake in this area.2
You might want to explore
Lumi's weekly note
A short email when we publish something useful. No spam, unsubscribe anytime.