Skip to content

fix(cloud): require CSRF state in the WorkOS login callback - #1886

Open
ra-co88 wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
ra-co88:fix/login-csrf-state-mandatory
Open

fix(cloud): require CSRF state in the WorkOS login callback#1886
ra-co88 wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
ra-co88:fix/login-csrf-state-mandatory

Conversation

@ra-co88

@ra-co88 ra-co88 commented Aug 30, 2026

Copy link
Copy Markdown

What

The WorkOS login callback now requires a valid, unconsumed CSRF state parameter on every request. Missing state, unknown state, or a replayed (already consumed) state each return 400 before any WorkOS API call is made.

Why

Login CSRF: an attacker can craft a callback URL that logs the victim into the attacker's account. The state parameter ties the callback to a login flow the user actually initiated — without enforcing it unconditionally, the callback accepts forged authorization codes. The check now happens before any network call to WorkOS, so forged requests are rejected at zero cost.

What changed

  • The callback handler rejects requests with no state (400) before any WorkOS call.
  • State values are single-use: a replayed state returns 400.
  • A fresh state matching the browser's cookie proceeds to the session exchange (302).

Breaking changes

Flows that initiate login server-side and construct the callback URL without a state parameter will now be rejected. If you drive login from a server, generate a random nonce, persist it server-side (or sign it), and pass it as state — the callback validates it against the cookie it sets.

Test plan

Focused suite on the callback handler (apps/cloud/src/auth/workos-callback-state.node.test.ts):

  • no state → 400, no WorkOS call issued
  • replayed/consumed state → 400
  • fresh state matching cookie → 302 + session

All green against current main.

@ra-co88
ra-co88 force-pushed the fix/login-csrf-state-mandatory branch from 6102fbd to 4a0c27e Compare August 30, 2026 17:12
@ra-co88

ra-co88 commented Aug 30, 2026

Copy link
Copy Markdown
Author

Heads-up on the red E2E (cloud 13of16) check here: it's failing on main itself (e.g. the Version Packages runs), so it's pre-existing rather than from this PR. It's the cap-eviction scenario tripping over workerd resetting session Durable Objects mid-initialize when the test opens its burst of sessions — diagnosis and a proposed fix in #1895.

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.

2 participants