-
Notifications
You must be signed in to change notification settings - Fork 11.5k
fix: GoogleCalendar - Ensure that Delegation Credentials are able to reuse access_token #21389
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Hey there and thank you for opening this pull request! 👋🏼 We require pull request titles to follow the Conventional Commits specification and it looks like your proposed title needs to be adjusted. Details: |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎ 1 Skipped Deployment
|
557e870 to
99a913a
Compare
| expect(async () => { | ||
| return auth.getTokenObjectOrFetch(); | ||
| }).rejects.toThrowError("Invalid token response"); | ||
| }).rejects.toThrowError("fetchNewTokenObject error"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we report the actual error
| if (json && json.myFetchError) { | ||
| // Throw error back as it isn't a valid token response and we can't process it further | ||
| throw new Error(json.myFetchError); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We report the actual error now instead of going forward with this json and then being unable to parse the obviously invalid token and then throwing 'Invalid token response' error.
This was hiding the actual reason behind the error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the helper functions are moved to utils.ts so that they can be shared with CalendarService.auth.test.ts as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, all the auth testing related tests are moved to CalendarService.auth.test.ts where we don't mock OAuthManager and are more reliably to test Authentication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test module has all the auth related tests moved from CalendarService.test.ts
38c2dbc to
8a75800
Compare
8a75800 to
66a4889
Compare
E2E results are ready! |
| return { | ||
| ...credential, | ||
| key: booleanKeyStatus, | ||
| delegatedTo: !!credential.delegatedTo, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure that delegatedTo isn't logged fully.
| safeStringify({ | ||
| enrichedHosts: enrichedHosts.map((host) => { | ||
| return { | ||
| userId: host.user.id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't log anything more than what we need.
| vi.mock("googleapis-common", async () => { | ||
| const actual = await vi.importActual("googleapis-common"); | ||
| return { | ||
| ...actual, | ||
| OAuth2Client: vi.fn().mockImplementation((...args: [string, string, string]) => { | ||
| lastCreatedOAuth2Client = { | ||
| type: "oauth2", | ||
| args, | ||
| setCredentials: setCredentialsMock, | ||
| isTokenExpiring: vi.fn().mockReturnValue(true), | ||
| refreshToken: vi.fn().mockResolvedValue({ | ||
| res: { | ||
| data: MOCK_OAUTH2_TOKEN, | ||
| status: 200, | ||
| statusText: "OK", | ||
| }, | ||
| }), | ||
| }; | ||
| return lastCreatedOAuth2Client; | ||
| }), | ||
| JWT: vi.fn().mockImplementation((config: MockJWT["config"]) => { | ||
| lastCreatedJWT = { | ||
| type: "jwt", | ||
| config, | ||
| authorize: vi.fn().mockResolvedValue(undefined), | ||
| }; | ||
| return lastCreatedJWT; | ||
| }), | ||
| }; | ||
| }); | ||
| vi.mock("@googleapis/admin", () => adminMock); | ||
| vi.mock("@googleapis/calendar", () => calendarMock); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved these here from CalendarService.test.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved here fromCalendarService.test.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved here fromCalendarService.test.ts
adf5260 to
64b5781
Compare
Graphite Automations"Add consumer team as reviewer" took an action on this PR • (05/23/25)1 reviewer was added to this PR based on Keith Williams's automation. "Add foundation team as reviewer" took an action on this PR • (05/25/25)1 reviewer was added to this PR based on Keith Williams's automation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cubic found 12 issues across 20 files. Review them in cubic.dev
React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.
| }); | ||
|
|
||
| // If no delegation-credential is updated, create one | ||
| if (updated.count === 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a new delegation-credential after an updateMany that returned 0 is vulnerable to a classic race condition. If two parallel requests run this code, both can see count === 0 and each create a new row, leading to duplicate credentials. This should be handled with an atomic upsert or a Prisma transaction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An upsert isn't possible at the moment because userId and delegationCredentialId isn't unique
packages/app-store/googlecalendar/lib/__tests__/CalendarService.test.ts
Outdated
Show resolved
Hide resolved
packages/app-store/googlecalendar/lib/__tests__/CalendarService.auth.test.ts
Show resolved
Hide resolved
93a047b to
d778249
Compare
36efbb3 to
ef45c63
Compare
|
E2E tests are failing @hariombalhara |
|
@Udit-takkar Passing now !! It was build issue from github |

What does this PR do?
Fixes PRI-277
This PR unifies OAuth and JWT authentication by abstracting the existing JWT implementations to use OAuthManager as well. This makes JWT and OAuth approach quite similar and easier to understand.
It in-turn allows us to reuse the access token for JWT flow too which is used by Delegation Credential flow
Key Changes:
CalendarAuthclass that handles both OAuth and JWT authentication through the same interfaceOAuthManagerto work with JWT, enabling access token reuse by creating credentials with tokens when neededgetCurrentTokenObjectsupport in OAuthManagerTests
CalendarServiceand moved auth based tests to separateCalendarService.auth.test.tsmodule. The tests in auth.test.ts dont mock OAuthManager and are better able to test auth flowMandatory Tasks (DO NOT REMOVE)
How should this be tested?