Skip to content

fix(mothership): connect integrations from chat without state_mismatch#4848

Merged
icecrasher321 merged 3 commits into
stagingfrom
fix/better-auth-flag
Jun 2, 2026
Merged

fix(mothership): connect integrations from chat without state_mismatch#4848
icecrasher321 merged 3 commits into
stagingfrom
fix/better-auth-flag

Conversation

@icecrasher321
Copy link
Copy Markdown
Collaborator

@icecrasher321 icecrasher321 commented Jun 2, 2026

Summary

  • Add browser-initiated GET /api/auth/oauth2/authorize that runs oAuth2LinkAccount inside the user's browser request, forwards the state cookie, and redirects to the provider
  • Point the oauth_get_auth_link handler (lib/copilot/tools/handlers/oauth.ts) at that endpoint instead of building the provider URL server-side.
  • No change to skipStateCookieCheck — Better Auth's state-cookie CSRF protection stays enabled for all flows (incl. social login).
  • Fix to track draft ttl time from click time insted of generation time (for mothership)

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jun 2, 2026 7:04pm

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented Jun 2, 2026

PR Summary

Medium Risk
Touches OAuth linking, session cookies, and credential draft timing; changes are scoped but auth flows are sensitive.

Overview
Chat and copilot OAuth connect links no longer call Better Auth's oAuth2LinkAccount on the server. oauth_get_auth_link now returns a URL to new GET /api/auth/oauth2/authorize, which the user opens in the browser.

That route enforces session, validates query via authorizeOAuth2Contract, checks workspace write access, restricts callbackURL to same-origin, creates the pendingCredentialDraft at click time (15‑minute TTL), then runs oAuth2LinkAccount with the browser request headers and forwards Set-Cookie so Better Auth's signed state cookie lands in the browser—fixing state_mismatch without disabling state checks.

Draft creation and direct provider redirects were removed from lib/copilot/tools/handlers/oauth.ts. The API validation contract baseline was bumped for the new route.

Reviewed by Cursor Bugbot for commit 10f1085. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 2, 2026

Greptile Summary

This PR fixes the state_mismatch error that occurred when connecting OAuth integrations from the copilot chat. The root cause was that oAuth2LinkAccount was called server-side inside the copilot tool handler, causing Better Auth's signed state cookie to be set on the server-to-server response rather than the user's browser — so when the provider redirected back, the cookie was absent and the state check failed.

  • Adds a new browser-initiated GET /api/auth/oauth2/authorize endpoint that calls oAuth2LinkAccount in the context of the user's actual browser request, forwards the signed state cookie from Better Auth's response to the browser via set-cookie, and then redirects the user to the provider.
  • The copilot oauth_get_auth_link handler is simplified to return a URL pointing at the new endpoint instead of calling Better Auth directly; the pending-credential-draft creation is moved into the new endpoint so its 15-minute TTL starts at actual click time.
  • The new endpoint validates callbackURL to be same-origin (prefix check against ${baseUrl}/), enforces workspace write access, and has full try/catch error handling with informative redirects on failure.

Confidence Score: 5/5

Safe to merge — the change is a targeted, well-reasoned fix with correct session checks, workspace access enforcement, and same-origin callbackURL validation throughout.

The new authorize endpoint is properly guarded: authenticated session required, workspace write access checked, callbackURL validated to be same-origin, and all error paths redirect gracefully. The copilot handler simplification removes the server-side auth call that was the source of the bug. No identified correctness issues in the changed code.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/app/api/auth/oauth2/authorize/route.ts New browser-initiated GET endpoint that runs oAuth2LinkAccount in the user's request, forwarding the signed state cookie to the browser; session check, workspace write-access guard, same-origin callbackURL validation, and try/catch error handling all look correct.
apps/sim/lib/copilot/tools/handlers/oauth.ts Simplified to return a /api/auth/oauth2/authorize URL instead of calling oAuth2LinkAccount server-side; all DB/auth logic moved to the new route; the workspaceId null-guard at the top of generateOAuthLink ensures the parameter is a string before it's set on the authorize URL.
apps/sim/lib/api/contracts/oauth-connections.ts Adds authorizeOAuth2QuerySchema and authorizeOAuth2Contract for the new GET endpoint; uses existing workspaceIdSchema primitive for workspaceId validation.
scripts/check-api-validation-contracts.ts Bumps totalRoutes and zodRoutes baseline from 761 to 762 to account for the new route.

Reviews (2): Last reviewed commit: "fix draft timing issue" | Re-trigger Greptile

Comment thread apps/sim/app/api/auth/oauth2/authorize/route.ts
@icecrasher321
Copy link
Copy Markdown
Collaborator Author

@greptile

@icecrasher321
Copy link
Copy Markdown
Collaborator Author

bugbot run

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 10f1085. Configure here.

@icecrasher321 icecrasher321 merged commit 5d9752d into staging Jun 2, 2026
14 checks passed
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