fix(auth): revoke refresh token on logout + strip code/state from URL on callback #385
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/mokosh-apps!385
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/MAPPS-336-spa-logout-revoke-url-strip"
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?
MAPPS-336: two surgical hardening items on the SPA OIDC surface.
Logout: the existing path cleared
sessionStorageandlocation.replace(hub_logout)but never calledrevoke_refresh_token. The function has existed atsrc/modules/oidc/flow.rs:415since the initial cutover; nothing in the SPA invoked it, so a rotated-but-not-revoked refresh family stayed usable at the OP until natural expiry (a stolen refresh outlived the user clicking "Log out"). Now the click reads the stored refresh token, firesrevoke_refresh_tokenas a Dioxusspawn(RFC 7009 returns 200 for unknown tokens, so a network blip never blocks the local cleanup), then proceeds with the existing clear + navigate sequence.Callback URL strip: the previous code relied on the Dioxus router's
history.replaceStateside-effect to scrub?code=&state=after the token exchange. Racy in practice - if the router skipped or deferred the rewrite the code lingered inwindow.location, in browser history, and (more dangerously) inRefererheaders on the next navigation. The exchange call is now followed by an explicithistory.replace_state_with_url(NULL, "", Some("/auth/callback"))BEFORE thematcharms run, so the sensitive query string is gone whether the exchange succeeded or failed.No new dependency (uses the existing
dioxus::prelude::spawnandweb_sys::Historyalready in the bundle), no schema change, no UX change.#MAPPS-336
MAPPS-336: two surgical hardening items on the SPA OIDC surface. Logout: the existing path cleared `sessionStorage` and `location.replace(hub_logout)` but never called `revoke_refresh_token`. The function has existed at `src/modules/oidc/flow.rs:415` since the initial cutover; nothing in the SPA invoked it, so a rotated-but-not-revoked refresh family stayed usable at the OP until natural expiry (a stolen refresh outlived the user clicking "Log out"). Now the click reads the stored refresh token, fires `revoke_refresh_token` as a Dioxus `spawn` (RFC 7009 returns 200 for unknown tokens, so a network blip never blocks the local cleanup), then proceeds with the existing clear + navigate sequence. Callback URL strip: the previous code relied on the Dioxus router's `history.replaceState` side-effect to scrub `?code=&state=` after the token exchange. Racy in practice - if the router skipped or deferred the rewrite the code lingered in `window.location`, in browser history, and (more dangerously) in `Referer` headers on the next navigation. The exchange call is now followed by an explicit `history.replace_state_with_url(NULL, "", Some("/auth/callback"))` BEFORE the `match` arms run, so the sensitive query string is gone whether the exchange succeeded or failed. No new dependency (uses the existing `dioxus::prelude::spawn` and `web_sys::History` already in the bundle), no schema change, no UX change. #MAPPS-336