fix(oidc): scope /oauth2/logout post_logout_redirect_uri to the id_token_hint's client #279
No reviewers
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
psa-systems/bunyip!279
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/BUNYIP-260-logout-id-token-hint-compliance"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
BUNYIP-260: close the cross-RP open-redirect surface on
/oauth2/logout.LogoutQuerypreviously acceptedpost_logout_redirect_uri+statewith no identifier of the calling client. The runtime looked up the URI against EVERY oauth_clients row'spost_logout_redirect_urisallowlist, so RP-A could craft a logout URL pointing at RP-A's registered redirect, bounce a victim mid-logout with attacker-chosenstatewhile the victim thought they were leaving RP-B.OpenID Connect RP-Initiated Logout 1.0 §3 fixes this with
id_token_hint: the calling RP presents the id_token the OP issued to it, the OP identifies the client fromaud, and ONLY that client's allowlist is consulted. Add the parameter toLogoutQuery, decode the hint via a newOidcProvider::verify_id_token_clienthelper (signature + issuer + known kid,expdeliberately NOT checked because RPs commonly hand in expired hints), and narrow the SQL lookup toclient_id = $1 AND disabled_at IS NULL AND $2 = ANY(post_logout_redirect_uris).Backwards compatibility: bare
/oauth2/logout(no redirect, no hint) keeps working as a "just sign me out" call - the request still revokes sessions, fires back-channel logout, and lands on "/". The only behaviour change is: if apost_logout_redirect_uriis supplied WITHOUT a verifiableid_token_hint, the redirect is refused and the user lands on "/" instead (logged at warn for operator visibility). RPs that want the redirect must pass the hint - exactly the spec-compliant shape.The audit also called out CSRF on GET /oauth2/logout (
<img src>revokes a victim's session); that's deliberately deferred. The hint-binding change collapses the OPEN-REDIRECT surface here without adding a POST requirement that would break every legitimate RP integration. A follow-up ticket can take the POST+CSRF question separately.#BUNYIP-260