OAuth 2.0 is the authorization framework underlying the majority of modern web application integrations: "Sign in with Google," "Connect your Slack workspace," "Authorize this app to access your GitHub repositories." It is also one of the most frequently misconfigured security mechanisms in web applications, with a distinct category of vulnerabilities that differ substantially from traditional injection or authentication flaws. Understanding OAuth security requires understanding the flows, the trust model, and the ways that each element of the authorization dance can be manipulated.
OAuth 2.0 and its identity layer extension, OpenID Connect (OIDC), are distinct specifications that are frequently confused. OAuth 2.0 handles authorization — delegating access to resources — while OIDC handles authentication — establishing identity. When an application says "Sign in with Google," it is using OIDC on top of OAuth 2.0: OAuth handles the token exchange, and OIDC adds the ID token that asserts who the user is. Security findings in the authentication flow often relate to OIDC implementation errors rather than pure OAuth issues, but they are discovered using the same testing methodology.
OAuth 2.0 Flows and Their Security Properties
Authorization Code Flow with PKCE
The authorization code flow is the correct flow for applications acting on behalf of users. The application redirects the user to the authorization server with a client ID and redirect URI, the user authenticates and grants consent, the authorization server returns a short-lived authorization code to the redirect URI, and the application exchanges the code for access and refresh tokens via a server-to-server call. PKCE (Proof Key for Code Exchange) extends this flow with a code challenge and code verifier — the application generates a random secret (the code verifier), hashes it (the code challenge), sends the hash with the authorization request, and presents the original secret during code exchange. This prevents authorization code interception attacks, where an attacker who intercepts the code cannot exchange it because they do not have the corresponding verifier. PKCE is mandatory for public clients (mobile apps, SPAs) and strongly recommended for confidential clients as well.
Client Credentials Flow
The client credentials flow is for machine-to-machine communication where there is no user involved — a backend service accessing an API using its own credentials. The client authenticates directly to the token endpoint using its client ID and secret. The primary security concern is client secret management: secrets stored in environment variables, leaked through CI/CD logs, or hardcoded in repositories. Client secrets should be rotated regularly, stored in secrets managers rather than environment variables, and scoped to the minimum permissions required.
Common Vulnerabilities and Testing Methodology
CSRF via Missing State Parameter
The OAuth state parameter is a random, unguessable value that the client generates, sends with the authorization request, and verifies upon receiving the callback. Its purpose is to prevent cross-site request forgery against the OAuth callback endpoint: without state validation, an attacker can craft an authorization URL that, when followed by a victim, associates the attacker's authorization code with the victim's session. Testing for this vulnerability involves initiating an OAuth flow, capturing the authorization URL, removing or modifying the state parameter, completing the flow in a different browser session, and observing whether the application accepts the callback without state verification. Applications that do not validate state are vulnerable to account takeover via CSRF on the OAuth callback.
Open Redirect in redirect_uri
The redirect_uri parameter specifies where the authorization server sends the authorization code after user consent. If the authorization server performs insufficient validation of this parameter — accepting partial matches, path traversal sequences, or subdomains of registered URIs — an attacker can redirect the authorization code to an attacker-controlled endpoint. Testing methodology: register a client application, note the registered redirect_uri, then attempt variations during Burp Suite interception — trailing slashes, path appending, subdomain substitution, URL encoding. A finding here is typically critical severity because it allows token theft from any user who can be directed to the attacker's authorization URL. Real-world examples include a 2013 Facebook OAuth flaw where redirect-URI/next validation rejected external domains but accepted any facebook.com subdomain, letting a researcher chain a regex bypass to redirect victims through a facebook.com subdomain and steal access tokens (disclosed by Nir Goldshlager via Facebook's White Hat program, February 2013), and a 2020 GitHub OAuth bug where a misconfigured third-party GitHub App allowed redirect_uri manipulation to steal OAuth tokens.
Token Leakage via Referrer Header
The implicit flow — where access tokens are returned directly in the URL fragment — was common in single-page applications before PKCE adoption. Tokens in URL fragments are visible in browser history, server access logs, and Referrer headers sent to third-party resources loaded on the page. This is why the implicit flow is deprecated in OAuth 2.1: even tokens in the fragment can leak through unexpected paths. Applications using the implicit flow should migrate to authorization code + PKCE. More broadly, any page that receives tokens as URL parameters (rather than the fragment) is vulnerable to token leakage via Referer header to embedded third-party scripts.
Insufficient Scope Validation
OAuth scopes define the permissions granted by the resource owner. Applications that request broader scopes than necessary violate least privilege and expose users to excessive permission grants. More critically, server-side scope validation failures — where the resource server accepts tokens with scopes that do not cover the requested operation — represent broken access control. Testing involves requesting tokens with minimal scopes and attempting to access resources that require elevated scopes; a vulnerable server returns the resource regardless. Also test for scope escalation: can a client modify its scope claim in a JWT access token if the server is not properly validating the token signature?
JWT Security in OAuth Contexts
When OAuth access tokens are implemented as JWTs, additional vulnerabilities apply. The alg:none attack — where a modified JWT header specifies no signing algorithm, causing a vulnerable server to accept unsigned tokens — was a critical vulnerability in multiple JWT libraries. Testing should verify that the server rejects tokens with alg:none, rejects tokens with algorithm substitution (replacing RS256 with HS256 and signing with the public key), and validates the iss claim against an allowlist. Fortress MSSP's web application security assessments include comprehensive OAuth and JWT security testing using both Burp Suite's OAuth scanner and manual testing techniques. Contact us to discuss your application security requirements.