OAuth 2.0 and OpenID Connect
OAuth 2.0 is delegated authorization — letting app.meridian.example act on a user's behalf against another service without ever seeing the user's password — and OpenID Connect layers authentication (who the user is) on top of it. The two are constantly confused, and the confusion causes real account-takeover vulnerabilities.
This topic separates them, walks the authorization-code-with-PKCE flow that is now the default, and names the mistakes that turn "log in with Google" into a compromise — with Meridian acting as both an OAuth client and a provider for its own partners.
OAuth Is Authorization, OIDC Is Authentication
OAuth grants scoped access to resources and hands back an access token; OIDC adds an ID token that proves who the user is. Using a raw OAuth access token as proof of identity is a classic, exploitable mistake, because an access token is not bound to your application as an audience — a token issued for another service can be replayed to log in as its owner. If you need login, you need OIDC.
The Authorization Code Flow with PKCE
The browser redirects to the provider, the user consents, an authorization code comes back to the app, and the app exchanges that code — plus a PKCE verifier it generated — for tokens. PKCE (proof key for code exchange) stops an intercepted authorization code from being redeemed by an attacker, because redemption requires the original secret verifier. This flow is now the default even for confidential clients; the older implicit flow is retired.
Scopes and Least Privilege
Scopes bound what a token can do. Requesting read:calendar instead of full account access limits the blast radius if the token leaks, and it is a trust signal to the user as much as a security control. Over-broad scope requests are a recurring problem: a leaked or malicious integration with sweeping scopes reaches far more than it ever needed.
Redirect URIs and the state Parameter
Two small parameters carry a lot of the flow's security. Strict redirect-URI matching prevents an attacker from diverting the authorization code to a URL they control, and a state value ties the response back to the request to block CSRF on the login flow itself. Loosening either — a wildcard redirect, a missing state — is a common shortcut that has led to real token theft.
OAuth 2.0 — answers "can this app do this action on the user's behalf?" It issues an access token for authorization.
OpenID Connect — answers "who is this user?" It adds an ID token for authentication and is built on OAuth. If you need login, you need OIDC; using an access token as proof of identity is the mix-up behind several account-takeover bugs.
- Using an OAuth access token as proof of identity instead of an OIDC ID token — access tokens are not audience-bound to your app and can be replayed from another service.
- Loose redirect-URI validation or open redirects in the flow, letting an attacker capture the authorization code or tokens.
- Omitting or not verifying the
stateparameter, exposing the login flow to CSRF. - Requesting broad scopes by default, so a leaked token or a malicious integration gets far more than it needs.
- Still using the implicit flow instead of authorization-code-with-PKCE.
- Not validating the ID token's
iss,aud,exp, and signature before trusting it.
- Use the authorization-code flow with PKCE for all client types, and retire the implicit flow.
- Enforce exact redirect-URI matching and validate
stateon every callback. - Use OIDC ID tokens for authentication and validate their
iss,aud,exp, and signature; do not infer identity from access tokens. - Request the narrowest scopes that work, and review third-party integration scopes regularly.
- Treat every token as sensitive — short-lived, transmitted only over TLS, and stored safely.
Knowledge Check
You need users to "log in with" an identity provider. Which token proves who they are?
- The OIDC ID token, issued for authentication
- The OAuth access token, since it comes from the same provider
- The refresh token, because it lasts the longest
- Any token will do, since they all come from the same login flow anyway
What attack does PKCE specifically defend against?
- An intercepted authorization code redeemed by an attacker
- Brute-forcing the user's password at the provider
- Reading the ID token's claims in transit
- Guessing the client secret of a confidential server-side app
Why is requesting the narrowest OAuth scopes a security practice, not just etiquette?
- A leaked token can only do what its scopes allow
- Narrow scopes make the token cryptographically stronger
- Broad scopes cause the authorization code flow to fail
- Scopes only affect how the consent screen looks
You got correct