Skip to content

Conversation

@Abhishek-Dige
Copy link

@Abhishek-Dige Abhishek-Dige commented Dec 27, 2025

Resolves #182.

Description

This PR fixes an authentication inconsistency for Google-authenticated users.
Previously, JWT sub was populated with the OAuth provider user ID, while downstream authorization expects the internal MongoDB _id, causing upload failures.

This change normalizes Google sign-in by mapping the authenticated user to the database record and injecting the MongoDB _id into the auth flow before JWT creation.

Live Demo (if any)

Not applicable.

Note for Maintainer

  • No frontend or upload logic was modified.
  • Credentials-based authentication remains unchanged.
  • Google OAuth could not be tested locally due to missing OAuth credentials; logic was verified via code path inspection.

Checkout

  • I have read all the contributor guidelines for the repo.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed email normalization in Google authentication to ensure consistency.
    • Improved sign-in flow handling for existing and new user accounts.
  • New Features

    • Enhanced session and token handling to properly include user roles.
    • Added configurable authentication page routes for sign-in and error pages.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 27, 2025

@Abhishek-Dige is attempting to deploy a commit to the mrimmortal09's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Dec 27, 2025

Walkthrough

The changes modify NextAuth configuration to improve Google OAuth sign-in handling. Email is consistently lowercased; dbUser tracking propagates user data across conditional branches. Sign-in flow now distinguishes between new and existing users, with role propagation into session/JWT and custom pages (signIn, error routes) added to authOptions.

Changes

Cohort / File(s) Summary
NextAuth Google Sign-in & Role Propagation
app/api/auth/[...nextauth]/options.ts
Normalized email to lowercase for Google sign-in; introduced dbUser container to track user state across branches; updated sign-in flow to handle existing users (update googleId if missing) and new users (create with verified email, default roles, passwordSet = false); propagated user roles into session and JWT token; ensured session user.id and token sub alignment; added pages property to authOptions with signIn and error routes

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant GoogleOAuth as Google OAuth
    participant NextAuth
    participant Database
    
    Client->>GoogleOAuth: Initiate sign-in
    GoogleOAuth-->>Client: Return email & profile
    Client->>NextAuth: Callback with credentials
    
    rect rgb(200, 220, 240)
    Note over NextAuth: Email normalization & lookup
    NextAuth->>NextAuth: Lowercase email
    NextAuth->>Database: Query user by email
    Database-->>NextAuth: dbUser (existing) or null
    end
    
    alt Existing User (no googleId)
        rect rgb(230, 200, 220)
        Note over NextAuth: Update existing user
        NextAuth->>Database: Update googleId
        Database-->>NextAuth: Refresh dbUser with googleId
        end
    else New User
        rect rgb(220, 230, 200)
        Note over NextAuth: Create new user
        NextAuth->>Database: Create user (verified=true,<br/>passwordSet=false, roles=[])
        Database-->>NextAuth: Return new user record
        NextAuth->>NextAuth: Set dbUser to new record
        end
    end
    
    rect rgb(240, 240, 200)
    Note over NextAuth: Populate session & JWT
    NextAuth->>NextAuth: Set user.id & roles from dbUser
    NextAuth->>NextAuth: Propagate roles into session
    NextAuth->>NextAuth: Include roles in JWT token
    end
    
    alt Password not set
        NextAuth-->>Client: Redirect to set-password
    else Password exists
        NextAuth-->>Client: Redirect to authenticated page
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective: fixing JWT identity normalization for Google-authenticated users, which directly addresses the root cause identified in issue #182.
Linked Issues check ✅ Passed The PR addresses the core requirement from #182: ensuring Google-authenticated users are mapped to internal user records so uploads work. JWT sub normalization, dbUser tracking, and session/token role propagation implement this mapping.
Out of Scope Changes check ✅ Passed All changes are scoped to auth flow normalization for Google users. The addition of the pages property (signIn/error routes) is a minor auth-related extension that supports the redirect logic needed for the fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/api/auth/[...nextauth]/options.ts (1)

121-133: Handle potential null from findOneAndUpdate.

If findOneAndUpdate returns null (e.g., due to a race condition where the user was deleted between the find and update), dbUser becomes null, and the identity normalization at lines 148-151 would silently skip setting user.id. This could cause the original OAuth provider ID to persist in the JWT.

Consider preserving the original existingUser reference as a fallback:

🔎 Proposed fix
       if (!existingUser.googleId && user.id) {
-        dbUser = await User.findOneAndUpdate(
+        const updatedUser = await User.findOneAndUpdate(
           { email: existingUser.email },
           {
             $set: {
               googleId: user.id,
               image: user.image || undefined,
               emailVerified: true,
             },
           },
           { new: true, runValidators: true }
         )
+        dbUser = updatedUser ?? existingUser
       }
🧹 Nitpick comments (1)
app/api/auth/[...nextauth]/options.ts (1)

147-157: Core fix correctly normalizes identity.

This addresses the root cause from issue #182 by ensuring the JWT sub contains the MongoDB _id rather than the Google OAuth provider ID. The conditional guards against null dbUser.

The (user as any) type assertion is pragmatic given NextAuth's typing constraints. For improved type safety, consider extending NextAuth's types via module augmentation in a next-auth.d.ts file.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1d8e6b and 05af69d.

📒 Files selected for processing (1)
  • app/api/auth/[...nextauth]/options.ts
🧰 Additional context used
🧬 Code graph analysis (1)
app/api/auth/[...nextauth]/options.ts (1)
model/User.ts (1)
  • IUser (3-14)
🔇 Additional comments (5)
app/api/auth/[...nextauth]/options.ts (5)

91-94: LGTM!

Custom pages configuration is properly added for sign-in and error routes.


111-119: LGTM!

Email normalization to lowercase ensures consistent lookups regardless of case variations in the OAuth profile. The dbUser container cleanly tracks the database record across conditional branches.


134-145: LGTM!

New user creation properly initializes all required fields including passwordSet: false and default roles: ['user']. The isNewUser flag correctly tracks new registrations for the redirect logic.


183-191: LGTM!

Session and JWT configuration uses sensible defaults with a 24-hour maximum age and 1-hour update interval.


162-180: Role propagation is correctly implemented.

The jwt callback stores user.roles in the token (line 177), and the session callback propagates it to session.user.roles (line 168). This enables role-based access control throughout the application. NextAuth type augmentation is already in place in types/next-auth.d.ts, properly extending Session.user and User with id and roles properties, so TypeScript will correctly recognize these assignments.

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.

[bug]: error while uploading papers if g-auth is used to sign in

1 participant