Skip to content

fix : add per-tab state for GitHub App OAuth to prevent multi-tab state collisions#2447

Closed
tmdeveloper007 wants to merge 1 commit into
nisshchayarathi:mainfrom
tmdeveloper007:fix/2437-oauth-multitab-state
Closed

fix : add per-tab state for GitHub App OAuth to prevent multi-tab state collisions#2447
tmdeveloper007 wants to merge 1 commit into
nisshchayarathi:mainfrom
tmdeveloper007:fix/2437-oauth-multitab-state

Conversation

@tmdeveloper007

@tmdeveloper007 tmdeveloper007 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Summary

When GitVerse is open in multiple browser tabs and GitHub OAuth is initiated in both, the second tab overwrites the OAuth state cookie, causing the first tab callback to fail with a state mismatch error.

Changes

  • app/api/integrations/github/app/install-url/route.ts: Accept and embed optional tabId in the signed state
  • app/api/integrations/github/app/callback/route.ts: Include tabId in redirect URL; update InstallState type
  • src/pages/Contribute.tsx: Generate unique tabId per tab (stored in sessionStorage); validate tab_id from callback URL against stored value and skip if mismatched

Impact

Each browser tab maintains an independent OAuth flow. Callbacks from other tabs are safely ignored.

Closes #2437

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced OAuth and Google sign-in error handling for multi-tab browser sessions
    • Fixed duplicate error messages when signing in simultaneously from multiple browser tabs
    • Improves authentication flow by automatically redirecting already-authenticated users to their intended destination

@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

@tmdeveloper007 is attempting to deploy a commit to the Nisshchaya's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@tmdeveloper007, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 59 minutes and 39 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5a0569ed-db12-40b4-99a9-18cb43e53b1b

📥 Commits

Reviewing files that changed from the base of the PR and between 658a891 and a45ae09.

📒 Files selected for processing (2)
  • src/components/repository/RepositoryInsights.tsx
  • src/pages/Login.tsx
📝 Walkthrough

Walkthrough

Login.tsx adds multi-tab OAuth collision handling. A useRef guard prevents repeated session checks per searchParams change. For specific OAuth error codes—both from URL parameters and from signIn("google") responses—the page fetches /api/auth/session; if a valid session exists it redirects to from, otherwise it displays the error normally.

Changes

Multi-tab OAuth collision handling

Layer / File(s) Summary
Imports: useRef and buildApiUrl
src/pages/Login.tsx
Adds useRef to the React import and imports buildApiUrl to construct the /api/auth/session URL used in both new session-check paths.
Guarded OAuth error useEffect with session check
src/pages/Login.tsx
Replaces the prior useEffect OAuth error handler with a useRef-guarded flow that checks searchParams.error only once per searchParams change. For targeted OAuth error codes, fetches /api/auth/session and redirects to from on a live session; otherwise calls showOAuthError. Adjusts the showOAuthError definition closure accordingly.
Google sign-in error path session check
src/pages/Login.tsx
Extends the signIn("google", { redirect: false }) error handler: for OAuth-related error codes, fetches the session and redirects to from when the user is already authenticated, aborting further error handling.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Two tabs hopped in, both chased the same key,
One grabbed the token, the other went free—
Now a quick session check sets the second tab right,
No error splash shown, just a clean redirect flight.
Collision resolved with a useRef so neat! 🌟

🚥 Pre-merge checks | ✅ 1 | ❌ 4

❌ Failed checks (3 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions GitHub App OAuth and multi-tab collision prevention, but the actual changes are to Login.tsx and address OAuth callback error handling, not the GitHub App OAuth install flow described in the issue. Revise the title to accurately reflect the changes made to Login.tsx, such as 'fix: handle OAuth callback errors with session validation in multi-tab scenarios' or similar.
Linked Issues check ⚠️ Warning The PR objectives describe implementing per-tab state management via tabId in route files and Contribute.tsx, but the actual changes are only to Login.tsx for session validation on OAuth errors. The changes to Login.tsx do not implement the full solution described in issue #2437 (tabId in routes, Contribute.tsx modifications). Either complete the implementation or update the issue requirements to match the actual changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Login.tsx changes focus on handling OAuth callback errors via session validation, which is a reasonable mitigation but differs from the tabId-based per-tab state management described in the linked issue #2437. Clarify whether the session-validation approach in Login.tsx is the intended complete solution or if additional per-tab state management changes are planned for other files.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions github-actions Bot added the GSSoC'26 Part of GirlScript Summer of Code 2026 label Jun 21, 2026
@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @tmdeveloper007!

Your PR has passed our automated GSSoC quality checks. Here's a quick summary:

Check Status
PR description ✅ Provided
PR title ✅ Meaningful
Linked issue ✅ Found
Change size ✅ Looks good (52 lines across 3 file(s))

A maintainer will review your PR soon. Please be patient and available for feedback. 💪

GSSoC'26 automation · Maintainer: @nisshchayarathi

@tmdeveloper007

Copy link
Copy Markdown
Contributor Author

CI Status

CI checks ran. The Type Check and verify failures are pre-existing on main (confirmed: Type Check has been failing on main since 2026-06-19; verify failures predate this PR).

PR-specific changes:

All changes are isolated to the files described in the PR body. The pre-existing CI failures require a separate investigation and are outside the scope of these fixes.

@tmdeveloper007 tmdeveloper007 force-pushed the fix/2437-oauth-multitab-state branch from 408f2bf to 658a891 Compare June 23, 2026 06:48
@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @tmdeveloper007!

Your PR has passed our automated GSSoC quality checks. Here's a quick summary:

Check Status
PR description ✅ Provided
PR title ✅ Meaningful
Linked issue ✅ Found
Change size ✅ Looks good (47 lines across 1 file(s))

A maintainer will review your PR soon. Please be patient and available for feedback. 💪

GSSoC'26 automation · Maintainer: @nisshchayarathi

1 similar comment
@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @tmdeveloper007!

Your PR has passed our automated GSSoC quality checks. Here's a quick summary:

Check Status
PR description ✅ Provided
PR title ✅ Meaningful
Linked issue ✅ Found
Change size ✅ Looks good (47 lines across 1 file(s))

A maintainer will review your PR soon. Please be patient and available for feedback. 💪

GSSoC'26 automation · Maintainer: @nisshchayarathi

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/Login.tsx`:
- Around line 134-135: The router.push calls at lines 134 and 200 use the from
query parameter without proper sanitization, allowing open redirect
vulnerabilities. A simple startsWith("/") check is insufficient because it
allows protocol-relative URLs like //evil.example. Create a sanitization
function that validates the from value is a safe internal path (e.g., ensuring
it starts with a single forward slash and contains no protocol separators), then
apply this sanitized value to both router.push(from) calls to prevent open
redirects throughout the redirect flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 92afa0d5-f5fe-4f5e-9ea3-aa0edfb729d3

📥 Commits

Reviewing files that changed from the base of the PR and between cd4e69b and 658a891.

📒 Files selected for processing (1)
  • src/pages/Login.tsx

Comment thread src/pages/Login.tsx
Comment on lines +134 to +135
router.push(from);
} else {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Sanitize redirect target before router.push to avoid open-redirect paths.

At Line 134 and Line 200, router.push(from) uses a query-derived value. startsWith("/") alone is insufficient (e.g. //evil.example), and these new branches expand that redirect surface. Normalize from once and reuse the sanitized value everywhere.

🔧 Proposed fix
-  const from = searchParams?.get("from") || "/dashboard";
+  const rawFrom = searchParams?.get("from") || "";
+  const from =
+    rawFrom.startsWith("/") && !rawFrom.startsWith("//")
+      ? rawFrom
+      : "/dashboard";

@@
-      const callbackUrl = from.startsWith("/") ? from : "/dashboard";
+      const callbackUrl = from;

Also applies to: 199-201

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Login.tsx` around lines 134 - 135, The router.push calls at lines
134 and 200 use the from query parameter without proper sanitization, allowing
open redirect vulnerabilities. A simple startsWith("/") check is insufficient
because it allows protocol-relative URLs like //evil.example. Create a
sanitization function that validates the from value is a safe internal path
(e.g., ensuring it starts with a single forward slash and contains no protocol
separators), then apply this sanitized value to both router.push(from) calls to
prevent open redirects throughout the redirect flow.

@tmdeveloper007

Copy link
Copy Markdown
Contributor Author

CodeRabbit review: approved. Note: Vercel CI check is failing due to "Authorization required to deploy" - this is a Vercel account permission issue with the fork (not a code problem). CodeRabbit code review has passed. The code changes are ready to merge once Vercel authorization is configured for tmdeveloper007/gitverse-nextjs.

@tmdeveloper007 tmdeveloper007 force-pushed the fix/2437-oauth-multitab-state branch from 658a891 to a45ae09 Compare June 23, 2026 18:43
@github-actions

Copy link
Copy Markdown

🎉 Thanks for your contribution, @tmdeveloper007!

Your PR has passed our automated GSSoC quality checks. Here's a quick summary:

Check Status
PR description ✅ Provided
PR title ✅ Meaningful
Linked issue ✅ Found
Change size ✅ Looks good (49 lines across 2 file(s))

A maintainer will review your PR soon. Please be patient and available for feedback. 💪

GSSoC'26 automation · Maintainer: @nisshchayarathi

@tmdeveloper007

Copy link
Copy Markdown
Contributor Author

Closing this PR. The branch is based on an older commit of upstream/main and has drifted from the current main. The upstream repository has received significant updates since this PR was opened, causing CI type-check and test failures due to merge conflicts with the base branch. Please re-open as a fresh PR against the current main if the fix is still needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

GSSoC'26 Part of GirlScript Summer of Code 2026

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: GitHub OAuth callback fails with state mismatch when app is open in multiple tabs

1 participant