OAuth and OpenID Connect
Date: 2026-08-17
OAuth 2.0 is delegated authorisation — letting an app act on your behalf without your password. OpenID Connect is a thin layer on top that adds authentication. Using OAuth alone to log people in is the classic mistake, because it answers a question you didn’t ask.
OAuth 2.0 lets a user grant an application limited access to their data on another service, without sharing credentials. OpenID Connect (OIDC) extends it with an identity token, making it usable for login.
OAuth 2.0 "this app may read your
Google Calendar"
→ AUTHORISATION
OIDC "this user is alex@example.com,
verified by Google"
→ AUTHENTICATION
“Sign in with Google” is OIDC, not plain OAuth — Authentication vs Authorisation.
The cast
RESOURCE OWNER the user
CLIENT your application
AUTHORISATION issues tokens
SERVER (Google, Shopify…)
RESOURCE SERVER holds the data (the API)
The flow you should use
Authorisation Code with PKCE — for every client type, including server-side ones:
1 app redirects the user to the
authorisation server
+ client_id, scope, redirect_uri,
state, code_challenge
2 user authenticates and consents
3 redirect back with a short-lived
AUTHORISATION CODE
4 app exchanges the code (server-side,
with code_verifier) for tokens
5 app calls the API with the access token
Why the code, rather than the token, comes back through the browser: the code alone is useless without the exchange step, so a leaked redirect URL doesn’t leak the token.
PKCE (Proof Key for Code Exchange) adds a one-time secret proving the app exchanging the code is the one that started the flow. Originally for mobile apps; now recommended for all clients.
Flows to avoid
IMPLICIT deprecated. Returned the
token in the URL fragment
— logged, leaked, cached
PASSWORD GRANT the app collects the
user's password. Defeats
the entire purpose
CLIENT CREDENTIALS not for users at all —
machine-to-machine only.
Legitimate, different job
The parameters that are security controls
state CSRF protection. Generate,
store, verify on return.
← omitting it is a real
vulnerability, not a
formality
redirect_uri must be EXACTLY pre-registered.
Open redirects here are how
tokens get stolen
scope request the minimum. Users
reject broad consent screens,
and a leaked token does more
damage
nonce OIDC. Binds the ID token to
your request
state and exact redirect_uri matching are the two that get skipped, and both are exploitable.
The tokens you get back
ACCESS TOKEN call the API with this
short-lived, opaque or JWT
REFRESH TOKEN get a new access token
long-lived, store securely,
server-side only
ID TOKEN OIDC only. A JWT describing
WHO the user is
← for your app to read,
never to send to an API
The ID token is for you; the access token is for the API. Sending an ID token as a bearer credential is a common confusion.
The mistake worth naming
Using an access token as proof of identity. An access token says “the bearer may do X” — it doesn’t say who the bearer is, and it may have been issued to a different application entirely.
The consequence: an attacker with a token issued for their own app can present it to yours, and if you treat “the token works” as “this is that user”, you’ve authenticated them as someone else. This is why OIDC exists — the ID token is signed, audience-restricted, and verifiable as being for you.
Verification, if you consume tokens
signature against the provider's
published keys
iss the expected issuer
aud YOUR client id
exp / iat not expired
nonce matches yours
Use a maintained library. Hand-rolled JWT verification is a documented source of vulnerabilities — Sessions and Tokens.
Where you’ll meet it
Almost every platform integration in this vault: Shopify app authorisation, the Adobe and Google APIs, Klaviyo, and any “connect your account” flow. The flow is the same each time, which is the reason to learn it once — Shopify, Adobe Experience Cloud.