{"skill":{"slug":"oauth-debugger","displayName":"Oauth Debugger","summary":"Debug OAuth 2.0 and OIDC flows. Trace authorization code, PKCE, client credentials, and implicit flows. Diagnose redirect URI mismatches, scope issues, token...","description":"---\nname: oauth-debugger\ndescription: Debug OAuth 2.0 and OIDC flows. Trace authorization code, PKCE, client credentials, and implicit flows. Diagnose redirect URI mismatches, scope issues, token exchange failures, and JWKS configuration problems.\n---\n\n# OAuth Debugger\n\nDebug OAuth 2.0 and OpenID Connect flows without guessing. Trace each step of the authorization flow, identify where it breaks (redirect URI mismatch, scope issue, token exchange failure, JWKS misconfiguration), and provide the exact fix.\n\nUse when: \"oauth not working\", \"redirect URI mismatch\", \"invalid_grant\", \"login flow broken\", \"OIDC configuration\", \"token exchange failing\", \"PKCE error\", \"authorization code error\", or when SSO/social login breaks.\n\n## Commands\n\n### 1. `trace` — Trace OAuth Flow Step by Step\n\n#### Step 1: Discover OAuth Configuration\n\n```bash\n# OpenID Connect discovery\ncurl -s \"https://$AUTH_DOMAIN/.well-known/openid-configuration\" | python3 -c \"\nimport json, sys\nconfig = json.load(sys.stdin)\nprint('Authorization endpoint:', config.get('authorization_endpoint', '❌ MISSING'))\nprint('Token endpoint:', config.get('token_endpoint', '❌ MISSING'))\nprint('JWKS URI:', config.get('jwks_uri', '❌ MISSING'))\nprint('Supported flows:', config.get('grant_types_supported', ['not listed']))\nprint('Supported scopes:', config.get('scopes_supported', ['not listed']))\nprint('Token signing:', config.get('id_token_signing_alg_values_supported', ['not listed']))\n\"\n\n# Check JWKS endpoint\ncurl -s \"https://$AUTH_DOMAIN/.well-known/jwks.json\" | python3 -c \"\nimport json, sys\njwks = json.load(sys.stdin)\nfor key in jwks.get('keys', []):\n    print(f'Key ID: {key.get(\\\"kid\\\")} | Algorithm: {key.get(\\\"alg\\\")} | Use: {key.get(\\\"use\\\")}')\n\"\n```\n\n#### Step 2: Validate Authorization Request\n\nFor Authorization Code + PKCE flow:\n```bash\n# Check the authorization URL construction\n# Required parameters:\n# - response_type=code\n# - client_id=<your app>\n# - redirect_uri=<must match exactly>\n# - scope=<requested scopes>\n# - state=<CSRF protection>\n# - code_challenge=<PKCE S256 hash>\n# - code_challenge_method=S256\n\npython3 -c \"\nimport hashlib, base64, secrets\nverifier = secrets.token_urlsafe(32)\nchallenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b'=').decode()\nprint(f'code_verifier: {verifier}')\nprint(f'code_challenge: {challenge}')\nprint(f'code_challenge_method: S256')\n\"\n```\n\n#### Step 3: Diagnose Token Exchange\n\n```bash\n# Test token exchange\ncurl -s -X POST \"https://$AUTH_DOMAIN/oauth/token\" \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=authorization_code\" \\\n  -d \"code=$AUTH_CODE\" \\\n  -d \"redirect_uri=$REDIRECT_URI\" \\\n  -d \"client_id=$CLIENT_ID\" \\\n  -d \"client_secret=$CLIENT_SECRET\" \\\n  -d \"code_verifier=$CODE_VERIFIER\" | python3 -c \"\nimport json, sys\nresp = json.load(sys.stdin)\nif 'access_token' in resp:\n    print('✅ Token exchange successful')\n    print(f'Access token type: {resp.get(\\\"token_type\\\")}')\n    print(f'Expires in: {resp.get(\\\"expires_in\\\")}s')\n    print(f'Scopes: {resp.get(\\\"scope\\\")}')\n    if 'id_token' in resp:\n        print(f'ID token: present')\n    if 'refresh_token' in resp:\n        print(f'Refresh token: present')\nelse:\n    print(f'❌ Error: {resp.get(\\\"error\\\")}')\n    print(f'Description: {resp.get(\\\"error_description\\\")}')\n\"\n```\n\n### 2. `diagnose` — Common OAuth Errors\n\n**`invalid_grant`:**\n- Authorization code expired (usually 10 min TTL) → re-authorize\n- Code already used (one-time use) → don't retry, re-authorize\n- Redirect URI in token request doesn't match authorize request → exact match required\n- PKCE verifier doesn't match challenge → check encoding\n\n**`redirect_uri_mismatch`:**\n- Trailing slash matters: `http://localhost:3000` ≠ `http://localhost:3000/`\n- Scheme matters: `http` ≠ `https`\n- Port matters: `localhost:3000` ≠ `localhost:3001`\n- Path matters: `/callback` ≠ `/auth/callback`\n- Check provider's registered redirect URIs list\n\n**`invalid_client`:**\n- Wrong client_id or client_secret\n- Client credentials not sent correctly (Basic auth vs POST body)\n- Client deleted or disabled in provider\n\n**`invalid_scope`:**\n- Requested scope not enabled for this client\n- Scope format wrong (space-separated, not comma)\n- Provider renamed scope (e.g., `email` → `openid email`)\n\n**`access_denied`:**\n- User denied consent\n- Admin consent required but user is not admin\n- Conditional access policy blocked the request\n\n```markdown\n# OAuth Debug Report\n\n## Flow: Authorization Code + PKCE\n## Provider: Auth0 (tenant.auth0.com)\n\n## Trace\n1. ✅ Discovery: .well-known/openid-configuration found\n2. ✅ Authorization request: valid parameters\n3. ✅ User authenticated and consented\n4. ❌ Token exchange: `invalid_grant`\n\n## Diagnosis\n- Redirect URI in token request: `http://localhost:3000/callback`\n- Redirect URI in authorize request: `http://localhost:3000/callback/`\n- 🔴 **Trailing slash mismatch** — must be identical in both requests\n\n## Fix\nChange redirect_uri in token request to `http://localhost:3000/callback/` (with trailing slash)\nOR update authorize request to omit trailing slash.\nAlso update provider's registered redirect URIs to match.\n```\n\n### 3. `test-flow` — Simulate OAuth Flows\n\n**Client Credentials (machine-to-machine):**\n```bash\ncurl -s -X POST \"https://$AUTH_DOMAIN/oauth/token\" \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=client_credentials\" \\\n  -d \"client_id=$CLIENT_ID\" \\\n  -d \"client_secret=$CLIENT_SECRET\" \\\n  -d \"audience=$API_AUDIENCE\"\n```\n\n**Refresh Token:**\n```bash\ncurl -s -X POST \"https://$AUTH_DOMAIN/oauth/token\" \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=refresh_token\" \\\n  -d \"refresh_token=$REFRESH_TOKEN\" \\\n  -d \"client_id=$CLIENT_ID\"\n```\n\n### 4. `security-check` — Audit OAuth Implementation\n\nFlag security issues:\n- Implicit flow in use (deprecated, tokens in URL fragment)\n- No PKCE on public clients (authorization code interception)\n- State parameter missing (CSRF vulnerability)\n- Token in URL query string (logged everywhere)\n- Wildcard redirect URIs (open redirect)\n- Long-lived access tokens without refresh (> 1 hour)\n- Client secret in frontend code (exposed to users)\n","topics":["Debug"],"tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":347,"installsAllTime":13,"installsCurrent":0,"stars":0,"versions":1},"createdAt":1777628592979,"updatedAt":1778492818233},"latestVersion":{"version":"1.0.0","createdAt":1777628592979,"changelog":"Initial release: A comprehensive toolkit for debugging and testing OAuth 2.0 and OIDC flows.\n\n- Trace and diagnose issues in Authorization Code, PKCE, Implicit, and Client Credentials flows.\n- Detect and explain common errors such as redirect URI mismatches, scope problems, and invalid grants.\n- Provide ready-to-use commands for discovery, token exchange, and manual flow simulation.\n- Includes security auditing tips to catch unsafe configurations like missing PKCE, exposed secrets, or usage of deprecated flows.\n- Clear step-by-step troubleshooting with actionable fix suggestions.","license":"MIT-0"},"metadata":null,"owner":{"handle":"charlie-morrison","userId":"s17cttbdxry5kkyafjw983mq8s83p4y3","displayName":"charlie-morrison","image":"https://avatars.githubusercontent.com/u/271589886?v=4"},"moderation":null}