Skip to content

Set SameSite=None on the OAuth state cookie so form_post callbacks keep it - #2946

Open
RaphaelFakhri wants to merge 1 commit into
instantdb:mainfrom
RaphaelFakhri:fix-oauth-cookie-samesite
Open

RaphaelFakhri wants to merge 1 commit into
instantdb:mainfrom
RaphaelFakhri:fix-oauth-cookie-samesite

Conversation

@RaphaelFakhri

Copy link
Copy Markdown

Fixes #2892

Summary

/runtime/oauth/start sets the __session state cookie without a SameSite attribute, so browsers apply the Lax default. The generic OAuth client asks providers for response_mode=form_post, which makes the callback a cross-site POST to /runtime/oauth/callback. Browsers do not send Lax cookies on cross-site POSTs, except for Chrome's short-lived "Lax + POST" allowance on cookies younger than two minutes. Sign-ins that take longer, such as 2FA or passkey prompts, fail with {"type":"oauth-error","error":"Missing cookie."}.

Changes

  • server/src/instant/runtime/routes.clj: set SameSite=None on the state cookie whenever it is Secure. In dev, where the cookie is not Secure, it stays Lax, because browsers reject SameSite=None without Secure.
  • server/test/instant/runtime/routes_test.clj: add a test that calls /runtime/oauth/start through the handler and checks that the Set-Cookie header includes Secure and SameSite=None.

Testing

clojure -M:test -v instant.runtime.routes-test/oauth-start-cookie-is-sent-on-cross-site-callback
  • Without the change: 1 failure. The header is __session=instantdb_...; HttpOnly; Secure; Expires=...; Path=/runtime/oauth.
  • With the change: 0 failures. The header includes SameSite=None.
  • clojure -M:test -n instant.runtime.routes-test: 25 tests, 256 assertions, 0 failures.
  • clojure -M:lint on both files: 0 errors, 0 warnings.

…ep it

The runtime OAuth flow asks providers for response_mode=form_post, so the
callback arrives as a cross-site POST. Without a SameSite attribute,
browsers treat the __session cookie as Lax and drop it on that POST once
the sign-in takes longer than two minutes (2FA, passkeys), and the
callback fails with "Missing cookie."

Fixes instantdb#2892
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d57a8b22-2af7-45c1-b077-b396a995523f
📥 Commits

Reviewing files that changed from the base of the PR and between b97a116 and 2cde2fa.

📒 Files selected for processing: 2
  • server/src/instant/runtime/routes.clj
  • server/test/instant/runtime/routes_test.clj

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

OAuth session cookies now use SameSite=None outside development and SameSite=Lax in development. A new OAuth-start test checks the HTTPS response status and session cookie attributes.

Changes: OAuth session cookie

Layer / File(s) Summary
Set and verify OAuth cookie attributes
server/src/instant/runtime/routes.clj, server/test/instant/runtime/routes_test.clj
The OAuth route sets SameSite=None outside :dev and SameSite=Lax in :dev. The test checks that an HTTPS OAuth-start response returns status 302 and sets a Secure session cookie with SameSite=None.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: dwwoelfel

Merge Risk: ⚪ Minimal · up to 2cde2

The supplied context indicates the OAuth cookie is configured for cross-site callbacks while remaining Secure outside development. No actionable merge risk is established.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title clearly identifies the main change: setting SameSite=None on the OAuth state cookie to support form_post callbacks.
Description check Passed The description directly explains the OAuth cookie issue, the code and test changes, and the reported validation results.
Linked Issues check Passed Issue #2892 requires the server-set OAuth state cookie to use SameSite=None; Secure for cross-site form_post callbacks. oauth-start sets :secure outside :dev and sets :same-site to :none…
Out of Scope Changes check Passed The changes are limited to the OAuth state-cookie attributes and an automated /runtime/oauth/start regression test. These changes directly support issue #2892. No unrelated implementation or test ch…
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
Full details: Linked Issues check

Explanation

Issue #2892 requires the server-set OAuth state cookie to use SameSite=None; Secure for cross-site form_post callbacks. oauth-start sets :secure outside :dev and sets :same-site to :none when secure. It keeps :lax in :dev, where SameSite=None would be rejected. The added handler test checks the __session cookie for Secure and SameSite=None.

Full details: Out of Scope Changes check

Explanation

The changes are limited to the OAuth state-cookie attributes and an automated /runtime/oauth/start regression test. These changes directly support issue #2892. No unrelated implementation or test changes are identified.

Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (2 skipped: 2 unsupported.)

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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.

OAuth web redirect fails with "Missing cookie." — __session lacks SameSite=None while the flow uses response_mode=form_post

1 participant