Skip to content

fix(auth): verify one-time token before fetching session - #484

Merged
leoisadev1 merged 1 commit into
mainfrom
fix/auth-ott-verification
Jan 6, 2026
Merged

fix(auth): verify one-time token before fetching session#484
leoisadev1 merged 1 commit into
mainfrom
fix/auth-ott-verification

Conversation

@leoisadev1

Copy link
Copy Markdown
Member

Summary

Fixes the auth getting stuck after GitHub OAuth redirect. Users were seeing "Sign in with GitHub" even after successful authentication.

Root Cause

The crossDomain plugin creates a one-time token (ott) after OAuth callback and redirects to the frontend with ?ott=token. However, the StableAuthProvider was fetching the session immediately on mount without verifying the ott token first, causing auth to fail silently.

Changes

  • Check for ott parameter in URL on component mount
  • Verify the token via authClient.crossDomain.oneTimeToken.verify() before fetching session
  • Remove ott from URL after processing to prevent re-verification on refresh

Testing

  • Type check passes (bun check-types)
  • Build succeeds (bun run build in apps/web)

The crossDomain plugin creates a one-time token (ott) after OAuth
callback and redirects to frontend with ?ott=token. However, the
frontend never verified this token before fetching the session,
causing auth to get stuck showing 'Sign in with GitHub' even after
successful OAuth.

This fix:
- Checks for ott param in URL on mount
- Verifies token via crossDomain.oneTimeToken.verify() before fetching session
- Removes ott from URL after processing to prevent re-verification
@railway-app

railway-app Bot commented Jan 6, 2026

Copy link
Copy Markdown

🚅 Deployed to the openchat-pr-484 environment in OpenChat

Service Status Web Updated (UTC)
web ✅ Success (View Logs) Web Jan 6, 2026 at 11:13 pm

@railway-app
railway-app Bot temporarily deployed to OpenChat / openchat-pr-484 January 6, 2026 23:09 Destroyed
@github-actions

github-actions Bot commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

🚀 Preview Deployment Ready

Environment URL
Frontend https://web-openchat-pr-484.up.railway.app
Convex Dashboard Dashboard

Convex Preview Backend

  • Cloud URL: https://friendly-chickadee-976.convex.cloud
  • Site URL: https://friendly-chickadee-976.convex.site

🤖 Deployed automatically by GitHub Actions

@greptile-apps

greptile-apps Bot commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixed authentication stuck state after GitHub OAuth redirect by verifying one-time token before fetching session.

Key Changes

  • Added ott parameter detection in URL on StableAuthProvider mount
  • Call authClient.crossDomain.oneTimeToken.verify() before fetchSession() when ott is present
  • Remove ott from URL after processing to prevent re-verification

How It Works

The crossDomain plugin creates a one-time token (ott) after OAuth callback and redirects to the frontend. Previously, StableAuthProvider would fetch the session immediately without verifying the token first, causing the session to be empty and auth to fail silently. Now the token is verified first, which establishes the session, before fetching it.

Issues Found

  • Minor logic consideration: The .finally() block runs fetchSession() even when verify() fails. This may be intentional fallback behavior, but could also attempt session fetch with invalid credentials.

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk - fixes a critical auth bug with straightforward logic
  • Score reflects a well-targeted fix that addresses the root cause of the auth issue. The implementation is clean and follows the existing patterns. Deducted 1 point for the .finally() behavior that may attempt session fetch even on verification failure, which could be refined but isn't critical.
  • No files require special attention - the single file change is straightforward and properly scoped

Important Files Changed

Filename Overview
apps/web/src/lib/auth-client.tsx Added one-time token verification before session fetch to fix OAuth redirect auth failure. Logic is sound but has one minor edge case.

Sequence Diagram

sequenceDiagram
    participant User
    participant Frontend
    participant AuthServer as Better Auth
    participant GitHub
    participant Provider as StableAuthProvider

    User->>Frontend: Click sign in
    Frontend->>AuthServer: Start OAuth flow
    AuthServer->>GitHub: OAuth request
    GitHub->>User: Authorization prompt
    User->>GitHub: Approve
    GitHub->>AuthServer: OAuth callback
    AuthServer->>AuthServer: Create one-time credential
    AuthServer->>Frontend: Redirect with ott param
    
    Note over Provider: BEFORE FIX
    Provider->>AuthServer: fetchSession immediately
    AuthServer-->>Provider: No valid session yet
    Provider->>Provider: Auth gets stuck
    
    Note over Provider: AFTER FIX
    Provider->>Provider: Check URL for ott
    Provider->>AuthServer: Verify ott credential
    AuthServer-->>Provider: Session created
    Provider->>Provider: Clean URL params
    Provider->>AuthServer: fetchSession
    AuthServer-->>Provider: Return session
    Provider->>User: Successfully authenticated
Loading

@greptile-apps greptile-apps 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.

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +198 to +210
authClient.crossDomain.oneTimeToken
.verify({ token: ott })
.then(() => {
const url = new URL(window.location.href);
url.searchParams.delete("ott");
window.history.replaceState({}, "", url.toString());
})
.catch((err: unknown) => {
console.error("Failed to verify one-time token:", err);
})
.finally(() => {
fetchSession();
});

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.

logic: If verify() fails, fetchSession() still runs in .finally(). This means a failed/invalid token still attempts session fetch, which may not be the intended behavior - you might want to skip fetchSession() on verification failure.

Confidence: 3/5 - Depends on whether you want to attempt session fetch even with invalid ott tokens (could be intentional fallback behavior)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +194 to +195
const urlParams = new URLSearchParams(window.location.search);
const ott = urlParams.get("ott");

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.

style: Consider extracting window.location.search to a variable since it's used twice (here and in line 201 via window.location.href)

Suggested change
const urlParams = new URLSearchParams(window.location.search);
const ott = urlParams.get("ott");
const urlParams = new URLSearchParams(window.location.search);

Confidence: 2/5 - Minor style improvement, not critical

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@leoisadev1
leoisadev1 merged commit 0458152 into main Jan 6, 2026
8 checks passed
@leoisadev1
leoisadev1 deleted the fix/auth-ott-verification branch January 6, 2026 23:13
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