What is OAuth Misconfiguration?
OAuth lets users log into your app using their Google, GitHub, or other provider account. The flow involves redirecting the user to the provider, getting their approval, and receiving a token back at your callback URL. Every step in that chain is a potential attack point if implemented incorrectly.
The most dangerous mistake is skipping the state parameter. This random value ties the OAuth request to the user's browser session. Without it, an attacker can initiate an OAuth flow on their own, then trick a victim into completing it — logging the victim into the attacker's account or stealing the victim's token.
The second most common flaw is a loose redirect URI. If your OAuth callback accepts any URL under your domain (or worse, any URL at all), an attacker can redirect the token to a page they control. The provider thinks it's sending the token to your app. It's actually going to the attacker.
How does OAuth Misconfiguration work?
A typical OAuth misconfiguration happens when the callback route processes the authorization code without verifying the state parameter. This means there's no way to confirm that the OAuth flow was initiated by the same user who's completing it.
Here's what a vulnerable OAuth callback looks like:
// app/api/auth/callback/route.ts
export async function GET(req: Request) {
const url = new URL(req.url);
const code = url.searchParams.get('code');
// No state parameter check — CSRF is possible
// Exchange code for token
const tokenRes = await fetch('https://provider.com/oauth/token', {
method: 'POST',
body: JSON.stringify({
code,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: 'https://myapp.com/api/auth/callback',
}),
});
const { access_token } = await tokenRes.json();
// Log the user in immediately
return createSession(access_token);
}// app/api/auth/login/route.ts
export async function GET(req: Request) {
const state = crypto.randomUUID();
cookies().set('oauth_state', state, {
httpOnly: true, secure: true, sameSite: 'lax', maxAge: 600,
});
const authUrl = new URL('https://provider.com/oauth/authorize');
authUrl.searchParams.set('client_id', process.env.CLIENT_ID);
authUrl.searchParams.set('redirect_uri', ALLOWED_CALLBACK_URL);
authUrl.searchParams.set('state', state);
authUrl.searchParams.set('response_type', 'code');
return Response.redirect(authUrl.toString());
}
// app/api/auth/callback/route.ts
export async function GET(req: Request) {
const url = new URL(req.url);
const code = url.searchParams.get('code');
const state = url.searchParams.get('state');
const savedState = cookies().get('oauth_state')?.value;
if (!state || state !== savedState) {
return Response.json({ error: 'Invalid state' }, { status: 403 });
}
cookies().delete('oauth_state');
// ... exchange code for token with fixed redirect_uri
}Why do AI tools generate OAuth Misconfiguration vulnerabilities?
AI code generators produce OAuth flows that complete the login successfully — which is all the prompt asked for. The security properties of OAuth (state, nonce, strict redirects) are invisible when things work correctly.
- OAuth works without the state parameter. The login flow completes fine without state validation. The AI generates code that works, not code that's safe against CSRF.
- Provider docs vary in quality. Some OAuth provider examples skip security parameters for brevity. The AI trained on those examples reproduces the same gaps.
- Redirect URI validation is server config. Strict redirect URIs need to be configured at the OAuth provider, not just in code. The AI can't configure your Google Cloud Console.
The OAuth flow looks complete — users can sign in with Google, the token comes back, the session is created. But without state validation, an attacker can forge that entire flow and hijack the session.
Common OAuth Misconfiguration patterns
Missing state parameter
No CSRF protection on the OAuth flow. An attacker can initiate a login and trick a victim into completing it.
Wildcard redirect URIs
Accepting any path under the domain as a callback URL, letting attackers redirect tokens to pages they control.
Token in URL fragment
Using implicit grant flow where the access token appears in the URL — visible in browser history, referrer headers, and logs.
No PKCE in public clients
Single-page apps or mobile apps using the authorization code flow without PKCE, making the code interceptable.
How Flowpatrol detects OAuth Misconfiguration
Flowpatrol tests your OAuth implementation by walking through the authorization flow and checking each step for missing protections:
- 1Initiates the OAuth flow and checks whether a state parameter is generated and stored.
- 2Replays the callback with a forged or missing state parameter to test if the server rejects it.
- 3Probes redirect URI handling by modifying the callback URL to see if the server or provider accepts unexpected destinations.
- 4Reports the finding with the exact flow that succeeded without state validation and the redirect URIs that were accepted.
OAuth bugs are hard to spot because the happy path always works. Flowpatrol tests the abuse cases — forged state, swapped codes, redirected tokens — that real attackers use.
Related terms
Check your OAuth flow.
Flowpatrol walks through your login flow and tests for missing state parameters, open redirects, and token leaks. Paste your URL.
Try it free