This chapter surveys the most common ways OAuth clients get compromised and how to avoid them. Because clients vastly outnumber other OAuth components, simple mistakes—like treating OAuth as an authentication protocol without extra safeguards, mishandling client secrets or tokens, or leaking credentials to logs—can have outsized impact. The discussion emphasizes practical defenses that reduce the risk of code and token leakage, protect stored secrets, and preserve user trust and business reputation.
A major class of threats stems from browser-based flows. To prevent cross-site request forgery, clients should generate a high-entropy state value, bind it to the user session, and verify it on callback. Equally critical is strict redirect URI registration: use exact, fully qualified callback URLs. “Loose” registrations combined with permissive validation enable attacks such as stealing authorization codes via referrer leakage from user-controlled pages, or exfiltrating implicit-flow access tokens through open redirects that preserve URL fragments. The mitigations are to register precise callbacks, avoid hosting attacker-controlled content under OAuth paths, eliminate open redirects, and consistently validate state.
Beyond the browser, the chapter highlights credential and token handling pitfalls and native app guidance. Public and native clients cannot keep a client secret; prefer per-installation dynamic client registration instead of shipping embedded secrets. For native apps, use the system browser or modern secure in-app browser components rather than inspectable web-views, choose globally unique custom URL schemes, and apply PKCE to resist code interception. Transmit access tokens with the Authorization header, not in query parameters, to avoid logging and referrer leaks. Pick the right grant for the platform, store tokens securely, keep them out of logs, and, when using multiple authorization servers, register distinct redirect URIs to prevent mix-ups. Taken together, these practices materially harden OAuth clients against prevalent attacks.
Example of CSRF attack
Example of OAuth CSRF attack
Stolen authorization code
Hijacking of the authorization code
Referrer policy
Hijacking of the access token through the fragment
Hijacking of access token through the query parameter
FAQ
What is the OAuth state parameter and how does it prevent CSRF?
The state is a cryptographically random value the client generates and sends with the authorization request, then verifies on the redirect back. Because only the original client knows the expected value, mismatches (or a missing state) indicate a forged request and the client must abort, blocking CSRF attempts that try to inject an attacker’s code or token into the client.How should I generate and validate the state value safely?
- Generate with a cryptographically secure RNG (≈128 bits of entropy or more).- Store it server-side (for example, in the user’s session) and bind it to the user/flow.
- Include it in the outbound authorization request and compare it exactly on return.
- Reject the flow if it’s missing or doesn’t match.
- Don’t log state or expose it in analytics.
Why must I register a specific, exact redirect_uri?
Loose redirect_uri rules (domain-only or path prefixes) let attackers steer callbacks to pages they control under your domain, enabling code or token theft. Register the full, exact callback URL and design your app so no user-generated or attacker-controlled content can exist at or under that path. Exact matching at the authorization server is the safest policy.How can an attacker steal an authorization code via the Referer header?
If your redirect_uri allows subdirectories, an attacker can host a page under your domain as the callback. When the user lands there with ?code=..., that page loads an attacker-controlled resource; the browser sends a Referer header that includes the full URL (and the code), leaking it to the attacker. Use a fully specific redirect_uri and avoid hosting attacker-controlled content beneath it.How do open redirects enable stealing implicit-flow access tokens?
With implicit flow, the access token is in the URL fragment (#...). Many browsers preserve fragments across redirects. If your redirect_uri points to an open redirect on your domain, the browser forwards the user to the attacker’s site with the fragment intact (attacker.com#access_token=...), letting the attacker read it. Avoid open redirects and use exact redirect_uri matching; prefer flows that don’t expose tokens in the front channel.Should native/mobile apps embed a client_secret?
No. Anything shipped in a native or mobile app can be extracted. Treat native apps as public clients. If a secret is needed, obtain it at runtime (for example, via dynamic client registration) so each installation has distinct credentials, and never rely on a baked-in secret for security.Which OAuth grants should different client types use?
- Server-side web apps: Authorization Code grant (confidential clients).- In-browser JS apps: Implicit grant (per the book’s guidance) or consider code+PKCE in modern deployments.
- Native/mobile apps: Do not use implicit; use the system browser and employ PKCE with the authorization code flow.
Why is sending access_token in the URL dangerous, and what should I use instead?
Putting tokens in query parameters leaks them via logs, browser history, Referer headers, and copy/paste. Use the HTTP Authorization header: Authorization: BearerWhat is the Authorization Server Mix-Up attack and how can clients mitigate it?
When a client talks to multiple authorization servers, a malicious or confused redirect can cause the client to send secrets (codes or client secrets) to the wrong server. Mitigate by registering a distinct redirect_uri per authorization server and using it to unambiguously identify the AS handling the current flow.What are best practices for native apps (user-agent, redirect schemes, PKCE)?
- Use the system browser or OS-provided secure web-auth component, not a web-view you can inspect.- Use a globally unique custom URL scheme (for example, reversed DNS) to avoid interception.
- Employ PKCE to protect authorization codes from interception.
- Keep tokens and any runtime credentials out of logs and analytics.
OAuth 2 in Action ebook for free