`POST /auth/logout` — expire the session cookies, and revoke the session row when the caller could be authenticated.
/auth/logout⚠️ It runs for a caller who cannot authenticate, and that is the fix
An HttpOnly cookie can only be cleared by the server, so a sign-out gated
on a live session is a sign-out that fails exactly when it is needed. With
SelfAuthContext the extractor refused first and the handler never ran, so
four cases left the browser holding a refresh token after a deliberate
sign-out: an expired access cookie, an already-revoked session (the second
call of an idempotent logout), an api-key caller, and a token with no
origin_jti. [MaybeSelfAuth] collapses all four into one shape.
The None arm has authenticated nobody. It may only do what is safe for
an anonymous caller — clearing cookies is (the browser is discarding its own
state), revoking a server-side session is not, and that is why the revoke
hangs off Some.
Not a forced-logout primitive: rh-cl95c's CSRF layer refuses a
state-changing request the browser reports as cross-site, and it keys on
Sec-Fetch-Site rather than on a session cookie precisely so it still fires
on the routes that run without one — this being the first of them. (A
cookie-gated check would not have: SameSite=Strict withholds the cookie on
the very cross-site POST being defended against.)
Response Body
curl -X POST "https://example.com/auth/logout"Auth_list_public_idps GET
Previous Page
`POST /auth/refresh` — renew the access token from the refresh cookie. POST
The credential arrives in `__Host-vf_refresh`, not in the body: page script cannot read an `HttpOnly` cookie, so it cannot put the token there any more. This handler reads the jar and builds the port's [`RefreshInput`] from `{cookie, body.slug}` — the port and `refresh_for` are untouched, and know nothing about cookies. ⚠️ **Only `vf_session` and `vf_expires_at` are re-set.** Cognito's `REFRESH_TOKEN_AUTH` returns no new refresh token, so there is nothing to re-emit; the browser keeps the `vf_refresh` it has and a second renewal works. Re-setting it from `RefreshInput.refresh_token` would work too, but only by accident — it would write the same value back, and the first time Cognito *did* rotate, a handler that re-set the old value would pin the session to a dead credential. A missing cookie is the same uniform 401 as a bad one. #314's anti-enumeration property is that every probe-able failure is indistinguishable, and "you sent no cookie" is exactly such a probe.