fix gmail access token (#15374)

This commit is contained in:
neo773
2025-10-27 17:51:38 +05:30
committed by GitHub
parent 267af42412
commit b978b28760
5 changed files with 70 additions and 5 deletions
@@ -1,11 +1,16 @@
import { Module } from '@nestjs/common';
import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module';
import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/refresh-tokens-manager/drivers/google/google-api-refresh-access-token.module';
import { MicrosoftAPIRefreshAccessTokenModule } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/microsoft-api-refresh-access-token.module';
import { ConnectedAccountRefreshTokensService } from 'src/modules/connected-account/refresh-tokens-manager/services/connected-account-refresh-tokens.service';
@Module({
imports: [JwtModule, MicrosoftAPIRefreshAccessTokenModule],
imports: [
JwtModule,
GoogleAPIRefreshAccessTokenModule,
MicrosoftAPIRefreshAccessTokenModule,
],
providers: [ConnectedAccountRefreshTokensService],
exports: [ConnectedAccountRefreshTokensService],
})
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { TwentyConfigModule } from 'src/engine/core-modules/twenty-config/twenty-config.module';
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-tokens.service';
@Module({
imports: [TwentyConfigModule],
providers: [GoogleAPIRefreshAccessTokenService],
exports: [GoogleAPIRefreshAccessTokenService],
})
export class GoogleAPIRefreshAccessTokenModule {}
@@ -0,0 +1,41 @@
import { Injectable } from '@nestjs/common';
import { isDefined } from 'class-validator';
import { google } from 'googleapis';
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import {
ConnectedAccountRefreshAccessTokenException,
ConnectedAccountRefreshAccessTokenExceptionCode,
} from 'src/modules/connected-account/refresh-tokens-manager/exceptions/connected-account-refresh-tokens.exception';
import { type ConnectedAccountTokens } from 'src/modules/connected-account/refresh-tokens-manager/services/connected-account-refresh-tokens.service';
@Injectable()
export class GoogleAPIRefreshAccessTokenService {
constructor(private readonly twentyConfigService: TwentyConfigService) {}
async refreshTokens(refreshToken: string): Promise<ConnectedAccountTokens> {
const oAuth2Client = new google.auth.OAuth2(
this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_ID'),
this.twentyConfigService.get('AUTH_GOOGLE_CLIENT_SECRET'),
);
oAuth2Client.setCredentials({
refresh_token: refreshToken,
});
const { token } = await oAuth2Client.getAccessToken();
if (!isDefined(token)) {
throw new ConnectedAccountRefreshAccessTokenException(
'Failed to refresh google access token',
ConnectedAccountRefreshAccessTokenExceptionCode.REFRESH_ACCESS_TOKEN_FAILED,
);
}
return {
accessToken: token as string,
refreshToken,
};
}
}
@@ -3,6 +3,7 @@ import { Test, type TestingModule } from '@nestjs/testing';
import { ConnectedAccountProvider } from 'twenty-shared/types';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-tokens.service';
import { MicrosoftAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service';
import { isAccessTokenExpiredOrInvalid } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/utils/is-access-token-expired-or-invalid.util';
import {
@@ -32,6 +33,12 @@ describe('ConnectedAccountRefreshTokensService', () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ConnectedAccountRefreshTokensService,
{
provide: GoogleAPIRefreshAccessTokenService,
useValue: {
refreshTokens: jest.fn(),
},
},
{
provide: MicrosoftAPIRefreshAccessTokenService,
useValue: {
@@ -4,6 +4,7 @@ import { ConnectedAccountProvider } from 'twenty-shared/types';
import { assertUnreachable } from 'twenty-shared/utils';
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/google/services/google-api-refresh-tokens.service';
import { MicrosoftAPIRefreshAccessTokenService } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/services/microsoft-api-refresh-tokens.service';
import { isAccessTokenExpiredOrInvalid } from 'src/modules/connected-account/refresh-tokens-manager/drivers/microsoft/utils/is-access-token-expired-or-invalid.util';
import {
@@ -25,6 +26,7 @@ export class ConnectedAccountRefreshTokensService {
);
constructor(
private readonly googleAPIRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService,
private readonly microsoftAPIRefreshAccessTokenService: MicrosoftAPIRefreshAccessTokenService,
private readonly twentyORMManager: TwentyORMManager,
) {}
@@ -87,7 +89,7 @@ export class ConnectedAccountRefreshTokensService {
): Promise<boolean> {
switch (connectedAccount.provider) {
case ConnectedAccountProvider.GOOGLE: {
// Google's OAuth2Client handles token auto-refresh internally, no need to check token validity
// Google's access tokens are opaque and needs network calls to check if they are valid we default to true for now
return true;
}
case ConnectedAccountProvider.MICROSOFT: {
@@ -113,10 +115,9 @@ export class ConnectedAccountRefreshTokensService {
try {
switch (connectedAccount.provider) {
case ConnectedAccountProvider.GOOGLE:
return {
accessToken: '',
return await this.googleAPIRefreshAccessTokenService.refreshTokens(
refreshToken,
};
);
case ConnectedAccountProvider.MICROSOFT:
return await this.microsoftAPIRefreshAccessTokenService.refreshTokens(
refreshToken,