Skip to content

fix(auth): persist provider connection state for Google OAuth#508

Open
VIDYANKSHINI wants to merge 4 commits into
Dev-Card:mainfrom
VIDYANKSHINI:fix/google-oauth-connection-state
Open

fix(auth): persist provider connection state for Google OAuth#508
VIDYANKSHINI wants to merge 4 commits into
Dev-Card:mainfrom
VIDYANKSHINI:fix/google-oauth-connection-state

Conversation

@VIDYANKSHINI

Copy link
Copy Markdown
Contributor

Summary

This PR fixes an issue where the Google OAuth login flow authenticated the user but failed to persist the provider connection metadata (oAuthToken). By ensuring that Google's access token is explicitly upserted into the oAuthToken table upon successful login, downstream integrations that rely on provider connection states can now consistently identify Google-linked accounts, matching the behavior of the GitHub login flow.

Closes #493


Type of Change

  • Bug fix
  • New feature
  • Refactor (no functional change)
  • UI / Design change
  • Tests only (includes new regression tests)
  • Documentation
  • Infrastructure / DevOps
  • Security

What Changed

  • apps/backend/src/routes/auth.ts:
    • Inserted an app.prisma.oAuthToken.upsert block inside the GET /google/callback handler immediately after the user is created/updated.
    • Used encrypt(tokenData.access_token) to securely persist the token.
    • Hardcoded the google platform name and extracted the exact scopes (defaulting to openid email profile) so that the integration state matches what downstream integrations expect.
  • apps/backend/src/__tests__/auth.test.ts:
    • Added a new regression test suite leveraging app.inject and a mocked global fetch to simulate the Google authentication token/user endpoints.
    • Verified that prisma.oAuthToken.upsert successfully triggers with the right payload, preventing any future regressions on this flow.

How to Test

  1. Navigate to the backend folder (cd apps/backend).
  2. Run the specific auth tests: pnpm exec vitest run src/__tests__/auth.test.ts.
  3. Verify that the new tests successfully pass, confirming that the token is correctly upserted into the database mock.
  4. Manual Validation (Optional): Start the server, login via Google OAuth, and check the database (or via the /auth/me endpoint) to ensure your Google oAuthToken is correctly linked to your user account.

Checklist

  • My code follows the project's coding style (pnpm -r run lint passes).
  • TypeScript compiles without errors (pnpm -r run typecheck).
  • I have added or updated tests for the changes I made.
  • All tests pass locally (pnpm -r run test). (Note: The newly added auth tests pass perfectly. Any pre-existing failures in other modules like team.test.ts are from recent upstream refactoring)
  • I have updated documentation where necessary.
  • No new console.log or debug statements left in the code.
  • Breaking changes are documented in this PR description.

Screenshots / Recordings

N/A (Backend logic only)


Additional Context

This ensures parity across all authentication providers, avoiding unpredictable behaviour where some providers silently left users without linked connection entries.

Copilot AI review requested due to automatic review settings June 8, 2026 14:31
@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown

@VIDYANKSHINI is attempting to deploy a commit to the Prashantkumar Khatri's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds persistence of Google OAuth access tokens during the Google callback flow, and introduces a Vitest to verify token persistence on successful login.

Changes:

  • Persist encrypted Google access_token (and scopes) to oAuthToken via Prisma upsert during /auth/google/callback.
  • Add a backend test covering successful login + oAuthToken.upsert invocation.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
apps/backend/src/routes/auth.ts Encrypts and upserts Google OAuth access token + scopes, with non-blocking error handling.
apps/backend/src/tests/auth.test.ts Adds Vitest coverage for Google callback and token persistence behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +233 to +242
try {
const encryptedToken = encrypt(tokenData.access_token);
await app.prisma.oAuthToken.upsert({
where: { userId_platform: { userId: user.id, platform: 'google' } },
update: { accessToken: encryptedToken, scopes: tokenData.scope || 'openid email profile' },
create: { userId: user.id, platform: 'google', accessToken: encryptedToken, scopes: tokenData.scope || 'openid email profile' },
});
} catch (err) {
app.log.error({ err, userId: user.id }, 'Failed to persist Google OAuth token — authentication proceeds');
}
Comment on lines +240 to +242
} catch (err) {
app.log.error({ err, userId: user.id }, 'Failed to persist Google OAuth token — authentication proceeds');
}
Comment thread apps/backend/src/__tests__/auth.test.ts Outdated
Comment on lines +8 to +14
process.env.NODE_ENV = 'test';
process.env.PUBLIC_APP_URL = 'http://localhost:3000';
process.env.BACKEND_URL = 'http://localhost:3001';
process.env.MOBILE_REDIRECT_URI = 'devcard://auth';
process.env.GOOGLE_CLIENT_ID = 'test-google-id';
process.env.GOOGLE_CLIENT_SECRET = 'test-google-secret';
process.env.ENCRYPTION_KEY = '12345678901234567890123456789012';
Comment thread apps/backend/src/__tests__/auth.test.ts Outdated
},
};

global.fetch = vi.fn();
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

CI — All Checks Passed

Backend — PASS

Check Result
Lint PASS
Test PASS
Typecheck PASS

Mobile — SKIP

Check Result
Lint -
Test -

Web — SKIP

Check Result
Check -
Build -

Last updated: Tue, 09 Jun 2026 07:21:28 GMT

@Harxhit Harxhit added backend gssoc:approved Required label for every approved PR. Gives the base +50 points and enables contribution tracking. labels Jun 8, 2026
@VIDYANKSHINI

Copy link
Copy Markdown
Contributor Author

Hi team / @Harxhit,

I have addressed the recent PR review feedback and fixed the linting issues. Could you please let me know if any further changes are required from my end?

If everything looks good, I would appreciate it if someone could review and merge this PR.

@Harxhit

Harxhit commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Hi team / @Harxhit,

I have addressed the recent PR review feedback and fixed the linting issues. Could you please let me know if any further changes are required from my end?

If everything looks good, I would appreciate it if someone could review and merge this PR.

Please fix the lint issues.

Copilot AI review requested due to automatic review settings June 9, 2026 07:16

Copilot AI 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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.

Comment on lines +76 to +84
const app = await buildApp();

const res = await app.inject({
method: 'GET',
url: '/auth/google/callback?code=fake-code&state=fake-state',
cookies: {
oauth_state: 'fake-state',
},
});
Comment thread apps/backend/src/__tests__/auth.test.ts Outdated
process.env.GOOGLE_CLIENT_ID = 'test-google-id';
process.env.GOOGLE_CLIENT_SECRET = 'test-google-secret';
process.env.ENCRYPTION_KEY = '12345678901234567890123456789012';

Comment thread apps/backend/src/__tests__/auth.test.ts Outdated
it('allows authentication to succeed even if token persistence fails', async () => {
const mockUser = { id: 'user-123', username: 'testuser' };
mockPrisma.user.upsert.mockResolvedValue(mockUser);

Comment thread apps/backend/src/__tests__/auth.test.ts Outdated
// Should still succeed and redirect to dashboard
expect(res.statusCode).toBe(302);
expect(res.headers.location).toBe('http://localhost:3000/dashboard');

Comment on lines +237 to +242
const scopes = tokenData.scope || 'openid email profile';
await app.prisma.oAuthToken.upsert({
where: { userId_platform: { userId: user.id, platform: 'google' } },
update: { accessToken: encryptedToken, scopes },
create: { userId: user.id, platform: 'google', accessToken: encryptedToken, scopes },
});
@VIDYANKSHINI

Copy link
Copy Markdown
Contributor Author

Hi team / @Harxhit,
I have addressed the recent PR review feedback and fixed the linting issues. Could you please let me know if any further changes are required from my end?
If everything looks good, I would appreciate it if someone could review and merge this PR.

Please fix the lint issues.

"I have successfully fixed all the linting issues and the CI is completely green now. Ready for review/merge!"

@Harxhit

Harxhit commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Hi team / @Harxhit,
I have addressed the recent PR review feedback and fixed the linting issues. Could you please let me know if any further changes are required from my end?
If everything looks good, I would appreciate it if someone could review and merge this PR.

Please fix the lint issues.

"I have successfully fixed all the linting issues and the CI is completely green now. Ready for review/merge!"

Allow me some time please.

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

Labels

backend gssoc:approved Required label for every approved PR. Gives the base +50 points and enables contribution tracking.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Google OAuth login does not persist provider connection state required by downstream integrations

3 participants