OAuth 2.0 & OIDC: Modern Authentication Security
OAuth powers 'Login with Google' across the web — and is frequently misconfigured. Learn how it works, common vulnerabilities, and secure implementation.
Table of Contents
- OAuth 2.0 in Plain Terms
- The Authorization Code Flow
- PKCE: Securing Public Clients
- OpenID Connect (OIDC): Adding Authentication
- Common Vulnerabilities and Attacks
- Open Redirect via redirect_uri
- State Parameter CSRF
- Token Leakage via Referrer
- JWT Confusion Attacks
- Insufficient Scope Validation
- Secure Implementation Checklist
OAuth 2.0 in Plain Terms
OAuth 2.0 is an authorization framework, not an authentication protocol. This distinction matters enormously: OAuth answers "what is this application allowed to access?" — not "who is this user?" Its killer use case is delegated access: allowing a third-party app to read your Google Drive files without ever seeing your Google password.
The core actors in OAuth:
- Resource Owner: the user who owns the data
- Client: the third-party application requesting access
- Authorization Server: issues tokens after the user consents (e.g., Google's auth server)
- Resource Server: the API holding the user's data (e.g., Google Drive API)
The authorization server issues an Access Token the client uses to call the resource server on the user's behalf. Tokens are typically short-lived JWTs or opaque strings.
The Authorization Code Flow
For server-side web applications, the Authorization Code flow is the recommended approach:
- Client redirects user to the authorization server with
response_type=code,client_id,redirect_uri,scope, and a randomstateparameter - User authenticates and grants consent
- Authorization server redirects back to the client's
redirect_uriwith a short-livedcodeand thestatevalue - Client verifies the
statematches what it sent (CSRF protection), then exchanges thecodefor tokens via a back-channel POST request using itsclient_secret - Authorization server returns
access_tokenand optionallyrefresh_tokenandid_token
The back-channel exchange (step 4) is what makes this flow secure — the access token is never exposed in the browser's URL or history.
PKCE: Securing Public Clients
Mobile apps and SPAs (Single-Page Applications) cannot keep a client_secret safe — it would be visible in the app binary or JavaScript source. PKCE (Proof Key for Code Exchange, pronounced "pixie") solves this:
- Client generates a random
code_verifierand derivescode_challenge = BASE64URL(SHA256(code_verifier)) code_challengeis sent in the authorization requestcode_verifieris sent in the token exchange- Authorization server verifies the relationship — only the original client can complete the exchange
PKCE should be used for all OAuth clients in 2026, including confidential clients. It provides protection even if the authorization code is intercepted.
OpenID Connect (OIDC): Adding Authentication
OIDC is a thin identity layer built on top of OAuth 2.0. It adds the ID Token — a JWT signed by the authorization server that contains claims about the authenticated user (sub, email, name, etc.). OIDC is what makes "Login with Google" actually authenticate users rather than just authorize access to their data.
Key OIDC concepts:
- ID Token: a JWT for the client to verify who the user is — never send to APIs
- Access Token: for calling resource server APIs — the client should treat it as opaque
- UserInfo Endpoint: an API endpoint returning user claims when called with the access token
nonce: a random value included in the authorization request and verified in the ID token to prevent replay attacks
Common Vulnerabilities and Attacks
Open Redirect via redirect_uri
If the authorization server doesn't strictly validate the redirect_uri, an attacker can modify it to point to their own server, stealing the authorization code when the victim authorizes. Defense: register exact redirect URIs; disallow wildcard or pattern matching.
State Parameter CSRF
Omitting or not validating the state parameter allows an attacker to trick a victim's browser into completing an authorization flow the attacker initiated, potentially linking the victim's account to the attacker's identity. Defense: always generate a cryptographically random state and validate it on return.
Token Leakage via Referrer
The Implicit flow (now deprecated) returned tokens directly in the URL fragment, which could leak via Referer headers or browser history. Defense: never use the Implicit flow — use Authorization Code + PKCE instead.
JWT Confusion Attacks
JWTs are self-contained and must be carefully validated. Common mistakes:
- Accepting
alg: none— disable algorithm negotiation, always specify allowed algorithms explicitly - Using the RS256 public key as an HS256 secret — pin the expected algorithm server-side
- Not validating
iss,aud, andexpclaims
Insufficient Scope Validation
Access tokens should be scoped to the minimum necessary permissions. APIs must validate that the presented token has the required scope for each operation — don't assume a valid token equals full access.
Secure Implementation Checklist
- Use Authorization Code + PKCE for all clients
- Register exact, HTTPS-only redirect URIs
- Always validate the
stateparameter (or use PKCE, which provides equivalent protection) - Validate all JWT claims:
iss,aud,exp,nbf, algorithm - Store tokens in memory (not localStorage) in SPAs — use
HttpOnlycookies for refresh tokens on web apps - Implement token rotation: issue a new refresh token on each use and invalidate the old one
- Use short-lived access tokens (5–15 minutes) with refresh tokens for session continuity
- Audit all OAuth applications that have access to your authorization server regularly
- Never log or expose access tokens in URLs, logs, or error messages