All resources
// Resources

OAuth 2.0 and OpenID Connect Security Review Worksheet

Published June 15, 2026

Transaction binding through callback and refresh

Model one browser transaction from authorization request to logout. Store issuer, client ID, exact redirect URI, state, nonce where OIDC uses it, PKCE challenge, and browser-session binding. RFC 9700 requires exact redirect URI comparison except stated native loopback handling; a prefix rule such as https://app.example/callback?next= turns callback into code-leakage path. Public clients use PKCE, with S256 challenge and one-use verifier.

Test callback with missing state, state from another browser, reused code, wrong issuer, wrong audience, altered nonce, and redirect parameter that requests external destination. Each should stop before token exchange or local session creation. Capture redacted authorize URL, callback, token result, registered client configuration, issuer metadata, and server decision. Ensure codes and tokens do not land in application logs, referrer URLs, or history.

Refresh handling needs its own closure: public-client refresh tokens are sender constrained or rotated under RFC 9700. Replay an old refresh token and verify expected family revocation or security response. Fixes register exact URIs, consume transaction data, pin issuer metadata, and reject malformed bindings. Federation exceptions require documented account-linking rule; they never justify accepting a token merely because signature is valid.

Separate authorization-server trust from application account linking. An ID token identifies a subject only after issuer, audience, nonce, and signature validation; linking it to existing local account needs explicit product rule and collision handling. Test logout expectations too: local session removal may not end provider session, and that distinction should be visible in design. Do not accept resource-owner password grant as shortcut; RFC 9700 says it must not be used.

Bind one authorization transaction

Review OAuth as a sequence of bindings, not a button labeled “sign in.” Before redirect, server records configured issuer, client ID, exact redirect URI, browser-session reference, random state, PKCE challenge, challenge method, and OIDC nonce when an ID token is expected. RFC 9700 specifies exact redirect URI matching apart from defined native loopback port handling. A prefix rule such as https://app.example/callback?next= can allow code leakage through an unintended forwarder. Public clients use authorization code with PKCE; use S256, not a verifier exposed in the authorization request.

Run a normal authorization request and retain redacted request and callback captures. Then send callback with missing state, state from another browser, reused state, code issued to another client, altered PKCE verifier, expired code, wrong issuer, wrong audience, altered nonce, and a caller-supplied post-login destination. Each invalid case must stop before token exchange or local session creation. Expected response is a controlled error or restart action, never a session created from partial validation. Do not allow callback parameters to become an open redirect.

Token and account outcomes

At token exchange, verify code is one-use and bound to registered client. For OIDC, validate signature through trusted issuer keys, iss, aud, time claims, and nonce before using subject claims. An ID token is not automatically an API access token; resource server validates its own access-token audience and scope. Account linking needs explicit product rule for existing email or subject collision. Federation support does not justify trusting an assertion just because cryptography validates.

Test refresh separately. RFC 9700 requires refresh tokens for public clients to be sender-constrained or use rotation. Redeem a refresh token, then replay its predecessor. Observe documented family-revocation or security response, local-session result, and audit event. Record issuer metadata version, key set handling, redirect registration, transaction-store lifecycle, and all outcomes without logging codes, tokens, verifier, or nonce.

Logout and closure

Local logout removes local session; it may not terminate provider session. Test back-button, new-tab login, allowed return URL, and logout after provider failure so product behavior is deliberate. Delete state, nonce, and verifier after success, failure, timeout, and cancellation. Remediate with exact URI registration, server-bound transaction storage, PKCE enforcement, issuer pinning, and strict callback validation. A temporary migration exception names issuer, client, redirect, expiry, and test proving it cannot forward credentials. Closure reruns cross-browser state and old-refresh-token cases with fresh synthetic accounts.

Redirect registration evidence

Export registered redirect URIs from authorization server and compare them byte-for-byte with client configuration. Include scheme, host, path, encoding, and native loopback handling. Test a host case variant, added path segment, query parameter, fragment, and user-info trick; none should receive code. If multiple issuers are supported, bind each browser transaction to intended issuer and test a callback from the other issuer. Preserve registration export and redacted test timestamps as review evidence.

Transaction artifact

CheckOwnerStatusEvidenceExpected resultActual resultExceptionClosure
OIDC-CB-05 cross-browser callback stateauthentication ownerPassedredacted authorize/callback IDs, transaction-store trace, session querycallback stops before token exchange; no local sessioncontrolled restart returned; zero token request and zero session rownoneretain capture hash and rerun after callback or transaction-store change
OAUTH-RT-04 predecessor refresh replaymobile identity ownerOpentoken-family audit event and redacted replay timestamppredecessor replay triggers documented family responsereplay denied but sibling token remains activeEX-22, legacy client migration ends 2026-07-15 with shortened lifetimeenable family revocation, replay predecessor, verify sibling denial and audit event

Sources

Have a system that needs testing?