Repository navigation
Sign out browsers whose session has already ended - #1624
Merged
Merged
Conversation
Sign-out was declared on the session-authenticated API group, so a browser
whose sealed session no longer authenticated at click time got a 401 from
SessionAuth instead of being signed out. The console posts sign-out as a
top-level form navigation, so that error body was rendered as the page:
a screenful of {"_tag":"Unauthorized"}.
Move the endpoint to the public group and read the sealed session off the
request cookie. Nothing here needs authorizing — the request can only end
the session whose cookie it presents — and the handler already fell back to
"/" when the cookie would not unseal.
Cookies are dropped only when the request actually presented one, so the
now-public endpoint cannot be used cross-site to sign a user out.
@executor-js/cli
@executor-js/config
@executor-js/execution
@executor-js/sdk
@executor-js/codemode-core
@executor-js/runtime-quickjs
@executor-js/plugin-file-secrets
@executor-js/plugin-graphql
@executor-js/plugin-keychain
@executor-js/plugin-mcp
@executor-js/plugin-onepassword
@executor-js/plugin-openapi
executor
commit: |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | 16ea284 | Commit Preview URL Branch Preview URL |
Aug 17 2026, 05:22 PM |
RhysSullivan
marked this pull request as ready for review
August 17, 2026 17:37
omega-alpha-matt Bot
pushed a commit
to airbooksio/executor
that referenced
this pull request
Aug 18, 2026
) * test: repro sign-out answering with a raw Unauthorized page * fix: sign out browsers whose session has already ended Sign-out was declared on the session-authenticated API group, so a browser whose sealed session no longer authenticated at click time got a 401 from SessionAuth instead of being signed out. The console posts sign-out as a top-level form navigation, so that error body was rendered as the page: a screenful of {"_tag":"Unauthorized"}. Move the endpoint to the public group and read the sealed session off the request cookie. Nothing here needs authorizing — the request can only end the session whose cookie it presents — and the handler already fell back to "/" when the cookie would not unseal. Cookies are dropped only when the request actually presented one, so the now-public endpoint cannot be used cross-site to sign a user out.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Signing out could answer with a raw
{"_tag":"Unauthorized"}page instead of signing the browser out. Reported from the field.Cause
logoutwas declared onCloudAuthApi, which carries.middleware(SessionAuth). A browser whose sealed session no longer authenticated at click time got the middleware's 401 before the handler ran. The console posts sign-out as a top-level form navigation (the WorkOS hop is cross-origin, so it can't be a fetch), so that error body was rendered as the page.Nothing exotic is needed to reach it: a second open tab, a re-submit from history, or a session that expired or was revoked upstream while the tab sat open.
Change
Move the endpoint to
CloudAuthPublicApiand read the sealed session off the request cookie. There is nothing to authorize — the request can only end the session whose cookie it presents — and the handler already fell back to/when the cookie wouldn't unseal.Cookies are dropped only when the request actually presented one. Both are
SameSite=Lax, so a cross-site form POST arrives bare, gets the redirect, and cannot be used to sign a user out.Self-host is unaffected; it signs out through Better Auth.
Tests
e2e/cloud/logout-stale-session.test.ts— both scenarios fail onmainwith the reported body and pass here:vitest run --project cloud cloud/logout-stale-session.test.ts cloud/auth-session.test.ts cloud/auth-hint.test.ts— 8 passed, including the existing "logout ends the AuthKit session upstream" and "logout clears the hint with the session" contracts.typecheckclean;vitest run src/authin apps/cloud 73 passed.