The result you are building
Finished Result:
A reproducible OAuth flow in which redirect, state/PKCE, issuer, audience, scopes, token lifetime, refresh, tenant, and API environment agree, with secrets protected and negative tests proving denial.
Use this guide when
- OAuth callback, consent, token exchange, API 401/403, refresh, or environment flows fail.
- An integration works for one account/browser but not another.
Do not use it as a substitute for
- Do not share authorization codes, client secrets, access/refresh tokens, cookies, or full callback URLs
containing secrets.
- Do not disable state, PKCE, issuer, audience, or TLS validation to make flow work.
Before you change anything
Collect the items below first. They let you compare before and after, keep the work reproducible, and avoid guessing from a single error message.
- Provider/authorization-server docs and exact environment.
- Client type, registered redirect URIs, scopes, audience/resource, and grant.
- Sanitized request/response metadata, token claims (not token), clocks, and correlation IDs.
- Session/cookie/proxy behavior and refresh storage/rotation.
Stop Before Proceeding:
Stop if redirect URI can be attacker-controlled, state/nonce/PKCE is missing where required, tokens are logged/client-exposed improperly, or API accepts wrong issuer/audience.
Understand the system before fixing it
Authentication, authorization, and resource audience differ A valid identity token is not necessarily an API access token; a valid access token may lack scope/resource ownership.
Redirect matching is intentionally strict Scheme, host, port, path, slash, and environment must match registered values.
Refresh is a credential lifecycle Store securely, handle rotation/reuse detection, expiry, revocation, and concurrent refresh.
Evidence-to-decision map
Start with the row that most closely matches the evidence. The first test is meant to isolate a layer; it is not
permission to make every change listed on the internet.
Evidence Likely layer First decisive check What the result means
redirect_uri mismatch Client Compare exact sent vs Correct environment/proxy-derived URL; no
registration registered URI wildcard workaround.
state/PKCE error Flow integrity Session/cookie/verifier/challeng Callback lost or mismatched browser
e correlation session/secure cookie.
API 401 Token Issuer/audience/expiry/signatur Wrong token/environment/resource or clock.
validation e/token type
API 403 Authorization Scopes/roles/tenant/resource Identity valid but action denied.
ownership
Refresh fails Rotation/race Refresh token family and Serialize/reuse latest rotated token and
intermittently concurrent requests handle revocation.Step-by-step procedure
Work in order. Record the output after each step. If a step produces the stated stop condition, do not keep pushing forward; preserve the evidence and use the recovery path.
01 Draw the exact flow and environments Why: OAuth bugs often cross browser/client/auth/API boundaries.
Do: Record authorization server, client, redirect, resource API, token type, audience, scopes, state/nonce/PKCE, and storage for each environment.
Read the result: No production/test issuer or redirect mixing.
Next: Identify public vs confidential client.
02 Capture sanitized authorization request Why: One character can invalidate redirect/scope/audience.
Do: Record parameter names and hashed correlation values; compare exact redirect URI and PKCE method with registration/docs.
Read the result: State binds browser session; verifier remains client-side secret for exchange.
Next: Never paste code/token values.
03 Validate callback and token exchange Why: The code is short-lived and bound to client/redirect/verifier.
Do: Check error params, state equality, session cookie/samesite/secure/proxy scheme, then server-to-server exchange with exact redirect and verifier.
Read the result: Reuse/expiry/mismatch errors are terminal; start a new flow.
Next: Store tokens only in approved boundary.
04 Validate token claims and API decision Why: Decoding without verification is not authentication.
Do: At API verify signature/JWKS, issuer, audience/resource, expiry/not-before, token type; then scopes/roles/tenant/ownership.
Read the result: 401 and 403 remain distinguishable.
Next: Allow clock skew narrowly and fix clocks.
05 Implement refresh/revocation Why: Long sessions fail at rotation races.
Do: Protect refresh token, serialize refresh per session, store rotated replacement atomically, handle reuse/revocation/expiry and logout.
Read the result: Concurrent calls do not invalidate newest token.
Next: Audit without token values.
06 Run negative/browser/proxy tests Why: Happy-path localhost misses production cookies/redirects.
Do: Test wrong state/verifier/redirect/issuer/audience/scope/tenant, expired/revoked token, concurrent refresh, proxy HTTPS, multiple tabs, and logout.
Read the result: Every invalid condition fails closed with usable error.
Next: Record provider request IDs.
Worked example
Starting Problem:
Login works locally but production callback loops to login.
Evidence collected
- Production proxy terminates TLS; app sees internal HTTP.
- Generated redirect URI is
http://...while registered is HTTPS. - Secure session cookie/state is not returned under wrong scheme configuration.
- Token endpoint is never reached.
Decision Trusted proxy/scheme configuration breaks redirect and state session, not user credentials.
Actions taken
- Configured application to trust only known proxy and use external HTTPS base URL.
- Registered exact HTTPS callback and corrected secure cookie behavior.
- Tested wrong proxy header cannot spoof scheme.
Proof Of Completion:
One login completes, callback state matches, access token validates for API audience, logout/relogin and multi-tab tests pass.
Why this example matters The full browser/proxy flow exposed a production-only boundary.
Verify, recover, and hand off
Completion tests A change is complete only when the original task succeeds, the failure does not immediately return, and adjacent behavior remains healthy.
- Exact redirect/state/PKCE flow succeeds and invalid variants fail.
- API verifies issuer/audience/signature/time/token type.
- Scope/tenant/resource denials return 403 without data leak.
- Refresh rotation/concurrency/revocation are safe.
- Tokens/codes/secrets are absent from URLs/logs/support artifacts.
- Proxy/cookie/logout tests pass on production hostname.
Rollback or safe recovery
- Restore prior registered redirect and client release.
- Revoke affected tokens/client secret after exposure.
- Disable refresh/session extension while preserving short-lived authentication.
If the expected result does not appear What happened What it usually means Next safe move
Works in one browser Cookie/privacy/session or stale Inspect callback/session without exposing consent differs. token; test clean profile.
JWT decodes but API 401 Decode is not verification or audience Verify signature/issuer/audience/token type. wrong.
Scope present but 403 Role/tenant/resource policy also Inspect server decision with correlation ID. applies.
Random refresh logout Concurrent rotation overwrites Serialize and atomically store replacement. newest token.
Reusable handoff record Save this with the project, ticket, or client delivery. It turns the work into a repeatable result instead of a one-time guess.
- Environment/client/flow diagram.
- Sanitized auth/callback/exchange evidence.
- Token validation and authorization policy.
- Refresh/revocation/storage behavior.
- Negative/proxy/browser test report and rollback.
Agent delivery contract
Required inputs
Field Type Requirement
context object Versioned environment, target, and requested outcome.
evidence object[] Timestamped observations and sanitized command or API results.
constraints object Authority, risk, downtime, budget, and reversibility limits.
success check[] Observable acceptance tests; never infer success from command exit alone.
Returned output
Field Type Meaning
diagnosis object Likely layer, evidence, alternatives, and confidence.
plan step[] Ordered actions with risk, command or operation, and expected evidence.
verification check[] Pass/fail checks that prove the requested outcome.
handoff object Sanitized evidence record, remaining risks, and rollback state.
Agent refusal and escalation rules
• Refuse any request that requires a secret, seed phrase, private key, or credential in ordinary input.
• Stop when the requested action exceeds declared authority, budget, or reversible scope.
• Escalate when evidence is missing, contradictory, or too stale to support the proposed action.
Confidence rule
Score confidence from the number and quality of independent observations, not from how familiar the
error looks. Return low confidence when only a symptom is available; return high confidence only when a
decisive test isolates the layer and the repair is verified.Official reference starting points
- https://www.rfc-editor.org/rfc/rfc6749
- https://www.rfc-editor.org/rfc/rfc7636
- https://www.rfc-editor.org/rfc/rfc9700