Skip to content

feat(auth): add logout endpoint (DELETE /api/auth) + Sign out UI - #789

Open
fred0m wants to merge 1 commit into
outsourc-e:mainfrom
fred0m:feat/logout-endpoint
Open

fred0m wants to merge 1 commit into
outsourc-e:mainfrom
fred0m:feat/logout-endpoint

Conversation

@fred0m

@fred0m fred0m commented Sep 9, 2026

Copy link
Copy Markdown

Add logout endpoint (DELETE /api/auth) + Sign out button

Problem

Hermes Workspace with HERMES_PASSWORD enabled has no way to sign out. The only auth route is POST /api/auth (login); there is no logout endpoint and no UI affordance. Users must manually clear the claude-auth cookie or wait for the 30-day TTL to expire.

This matters for shared/borrowed devices and for deployments behind an upstream IdP (e.g. OIDC) where the workspace password is a second factor — after finishing a session there is no clean way to end it.

Changes

  • src/server/auth-middleware.ts: add clearSessionCookie() — emits a Max-Age=0 Set-Cookie with the same attributes as createSessionCookie() (HttpOnly, Secure per COOKIE_SECURE, SameSite=Strict, Path=/), so browsers accept the deletion.
  • src/routes/api/auth.ts: add DELETE /api/auth handler — extracts the claude-auth token from the cookie, revokes it via revokeSessionToken(), and returns the clearing Set-Cookie. Idempotent: returns {ok:true} even when no valid token is present.
  • src/components/workspace-shell.tsx: add handleLogout (DELETE + reload) and a "Sign out" button in the sidebar footer, shown only when authRequired && authenticated.

Verification

  • pnpm build passes.
  • pnpm vitest run src/server/auth-middleware.test.ts — 8/8 pass.
  • Manual: login → cookie works (200 on /api/skills) → DELETE /api/auth → Set-Cookie claude-auth=; Max-Age=0 → old cookie now 401.

Notes

  • CSRF: the cookie is SameSite=Strict; the existing login POST uses requireJsonContentType as an extra guard, but DELETE has no body by design. SameSite=Strict blocks cross-site DELETE from browsers.
  • The button is intentionally minimal (sidebar footer) to keep the diff small; happy to move it into Settings if maintainers prefer.

Fixes #790

Add a proper logout path for deployments with HERMES_PASSWORD enabled:

- server: DELETE /api/auth revokes the claude-auth session token and
  returns a Max-Age=0 Set-Cookie with matching attributes. Idempotent
  (returns ok even without a valid token) and rejects cross-site
  requests via Sec-Fetch-Site (defense in depth alongside SameSite=Strict).
- auth-middleware: clearSessionCookie() helper + revokeSessionToken()
  only persists when a token was actually removed (avoids needless I/O).
- UI: Sign out item in the desktop sidebar user menu and a sign-out
  button in the mobile hamburger drawer, shown only when auth is required.
- tests: clearSessionCookie coverage (Secure default + COOKIE_SECURE=0).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No way to sign out when HERMES_PASSWORD is enabled

1 participant