Skip to content

fix(pwa): unbreak sign-out, and stop echoing $PUBLIC_ORIGIN in the CLI hint - #108

Merged
ralyodio merged 1 commit into
masterfrom
fix/default-api-origin
Jul 30, 2026
Merged

fix(pwa): unbreak sign-out, and stop echoing $PUBLIC_ORIGIN in the CLI hint#108
ralyodio merged 1 commit into
masterfrom
fix/default-api-origin

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Two dashboard bugs, both fixed by handing appBar/CLI_HINT the request.

1. Sign-out is broken for everyone

csrfGuard rejects any POST whose _csrf doesn't match the mc_csrf cookie, and /auth/logout is a POST that isn't on the exempt list (/api/, /webhooks/, /cli/token, /cli/device/). The sign-out form carried no hidden field, so every click answered 403 bad csrf token.

This isn't host-specific — nobody could log out, on any domain.

appBar now takes the request rather than the user, since it needs the token as well as the identity. The field is written out instead of reusing csrfInput(): html.mjs is the view layer and imports nothing, and pulling in session.mjs would drag the database driver along with it.

2. The CLI hint still echoed $PUBLIC_ORIGIN

Users on app.logicsrc.com were told to point LOGICSRC_API at the generated Railway hostname. #105 added requestOrigin() for exactly this class of bug and fixed the device-flow URLs — the dashboard hint was missed. Its own comment names this symptom.

Not a hardcode swap: the same deployment answering on its Railway hostname still self-describes correctly.

Verification

Ran the app locally with PUBLIC_ORIGIN deliberately set to the Railway URL, to reproduce production:

Logout, real round trip (csrfGuard runs before auth, so this needs no login):

  • POST /auth/logout with no _csrf403 bad csrf token — the reported failure, reproduced
  • POST /auth/logout with the cookie's token → 302 → / — what the fixed form now sends

Dashboard, real render (seeded a session in the local DB, NODE_ENV=production so trust proxy is on):

  • Host: app.logicsrc.comLOGICSRC_API=https://app.logicsrc.com
  • Host: logicsrc-credentials-production.up.railway.app → still that host
  • sign-out form renders <input type="hidden" name="_csrf" value="…"> matching the cookie
  • zero up.railway.app occurrences left on the page

Tests: 9/9 pass (node --test in apps/pwa), including 4 new ones pinning the sign-out field, its placement inside the form, the no-token case, and escaping of the identity.

Still worth doing separately

config.origin is correct to keep for security decisions, and it is still wrong in production. PUBLIC_ORIGIN is set to the Railway URL, which leaves:

  • passkey.mjs expectedOrigin (and rpID) — passkey login/registration on app.logicsrc.com cannot succeed while these are pinned to the Railway host.
  • credshare.mjs invite links — invite emails embed ${config.origin}/teams/accept?..., so they point at the Railway host.

Both are a config fix, not code: set PUBLIC_ORIGIN=https://app.logicsrc.com on Railway. Note that changes the WebAuthn RP ID, so any passkey registered under the Railway host stops working and has to be re-registered.

🤖 Generated with Claude Code

…I hint

Two bugs on the dashboard, both fixed by handing appBar/CLI_HINT the request.

Sign-out was broken for everyone. csrfGuard rejects any POST whose _csrf does
not match the mc_csrf cookie, and /auth/logout is a POST that is not on the
exempt list, but the sign-out form carried no hidden field -- every click
answered 403 "bad csrf token". appBar now takes the request rather than the
user, because it needs the token as well as the identity. The field is written
out instead of reusing csrfInput(): html.mjs is the view layer and imports
nothing, and pulling in session.mjs would drag the database driver with it.

The "Connect the CLI" snippet still printed $PUBLIC_ORIGIN, so users on
app.logicsrc.com were told to point LOGICSRC_API at the generated Railway
hostname. #105 added requestOrigin() for exactly this and fixed the device-flow
URLs; the dashboard hint was missed. It now follows the request too, which is
not a hardcode swap -- the same deployment answering on its Railway hostname
still self-describes correctly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 898d550 into master Jul 30, 2026
5 checks passed
@ralyodio
ralyodio deleted the fix/default-api-origin branch July 30, 2026 17:56
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

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.

1 participant