Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions redisinsight/api/src/__mocks__/cloud-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,19 @@ export const mockCloudAuthGithubAuthUrl =
`&${new URLSearchParams({ scope: mockCloudAuthGithubRequest.scopes.join(' ') }).toString()}` +
'&prompt=login';

export const mockCloudIdToken = 'id_token_p6vA6A5tF36Jf6twH2cBOqtt7n';
export const mockCloudIdTokenNew = 'id_token_p6vA6A5tF36Jf6twH2cBOqtt7n-new';

export const mockTokenResponse = {
access_token: mockCloudAccessToken,
refresh_token: mockCloudRefreshToken,
id_token: mockCloudIdToken,
};

export const mockTokenResponseNew = {
access_token: mockCloudAccessTokenNew,
refresh_token: mockCloudRefreshTokenNew,
id_token: mockCloudIdTokenNew,
};

export const mockCloudAuthGoogleCallbackQueryObject = {
Expand Down
1 change: 1 addition & 0 deletions redisinsight/api/src/__mocks__/cloud-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const mockCloudApiCsrfToken: ICloudApiCsrfToken = {
export const mockCloudApiAuthDto: ICloudApiCredentials = {
accessToken: 'at_p6vA6A5tF36Jf6twH2cBOqtt7n',
refreshToken: 'rt_p6vA6A5tF36Jf6twH2cBOqtt7n',
idToken: 'id_token_p6vA6A5tF36Jf6twH2cBOqtt7n',
idpType: CloudAuthIdpType.Google,
csrf: mockCloudApiCsrfToken.csrf_token,
apiSessionId: 'asid_p6v-A6A5tF36J-f6twH2cB!@#$_^&*()Oqtt7n',
Expand Down
1 change: 1 addition & 0 deletions redisinsight/api/src/__mocks__/cloud-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ export const mockCloudApiHeaders = {
authorization: `Bearer ${mockCloudApiAuthDto.accessToken}`,
'x-csrf-token': mockCloudApiAuthDto.csrf,
cookie: `JSESSIONID=${mockCloudApiAuthDto.apiSessionId}`,
'Sm-Id-Token': mockCloudApiAuthDto.idToken,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,37 @@ describe('CloudAuthService', () => {
);
expect(service['authRequests'].size).toEqual(0);
});
it('should store idToken in session when present in token response', async () => {
expect(service['authRequests'].size).toEqual(1);
await service['callback'](mockCloudAuthGoogleCallbackQueryObject);
expect(sessionService.updateSessionData).toHaveBeenCalledWith(
mockCloudAuthGoogleRequest.sessionMetadata.sessionId,
{
accessToken: mockTokenResponse.access_token,
refreshToken: mockTokenResponse.refresh_token,
idToken: mockTokenResponse.id_token,
idpType: mockCloudAuthGoogleRequest.idpType,
},
);
});
it('should handle missing idToken gracefully', async () => {
const tokenResponseWithoutIdToken = {
access_token: mockCloudAccessTokenNew,
refresh_token: mockCloudRefreshTokenNew,
};
spy.mockResolvedValue(tokenResponseWithoutIdToken);
expect(service['authRequests'].size).toEqual(1);
await service['callback'](mockCloudAuthGoogleCallbackQueryObject);
expect(sessionService.updateSessionData).toHaveBeenCalledWith(
mockCloudAuthGoogleRequest.sessionMetadata.sessionId,
{
accessToken: tokenResponseWithoutIdToken.access_token,
refreshToken: tokenResponseWithoutIdToken.refresh_token,
idToken: undefined,
idpType: mockCloudAuthGoogleRequest.idpType,
},
);
});
it('should throw an error if error field in query parameters (CloudOauthMisconfigurationException)', async () => {
expect(service['authRequests'].size).toEqual(1);
await expect(
Expand Down Expand Up @@ -396,6 +427,57 @@ describe('CloudAuthService', () => {
{
accessToken: mockCloudAccessTokenNew,
refreshToken: mockCloudRefreshTokenNew,
idToken: mockTokenResponseNew.id_token,
idpType: mockCloudApiAuthDto.idpType,
csrf: null,
apiSessionId: null,
},
);
});

it('should store idToken in session when present in token response', async () => {
mockedAxios.post.mockResolvedValueOnce({ data: mockTokenResponseNew });

await service['renewTokens'](
mockSessionMetadata,
mockCloudApiAuthDto.idpType,
mockCloudApiAuthDto.refreshToken,
);

expect(sessionService.updateSessionData).toHaveBeenCalledWith(
mockSessionMetadata.sessionId,
{
accessToken: mockCloudAccessTokenNew,
refreshToken: mockCloudRefreshTokenNew,
idToken: mockTokenResponseNew.id_token,
idpType: mockCloudApiAuthDto.idpType,
csrf: null,
apiSessionId: null,
},
);
});

it('should handle missing idToken gracefully', async () => {
const tokenResponseWithoutIdToken = {
access_token: mockCloudAccessTokenNew,
refresh_token: mockCloudRefreshTokenNew,
};
mockedAxios.post.mockResolvedValueOnce({
data: tokenResponseWithoutIdToken,
});

await service['renewTokens'](
mockSessionMetadata,
mockCloudApiAuthDto.idpType,
mockCloudApiAuthDto.refreshToken,
);

expect(sessionService.updateSessionData).toHaveBeenCalledWith(
mockSessionMetadata.sessionId,
{
accessToken: tokenResponseWithoutIdToken.access_token,
refreshToken: tokenResponseWithoutIdToken.refresh_token,
idToken: undefined,
idpType: mockCloudApiAuthDto.idpType,
csrf: null,
apiSessionId: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export class CloudAuthService {
{
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
idToken: tokens.id_token,
idpType: authRequest.idpType,
},
);
Expand Down Expand Up @@ -344,6 +345,7 @@ export class CloudAuthService {
await this.sessionService.updateSessionData(sessionMetadata.sessionId, {
accessToken: data.access_token,
refreshToken: data.refresh_token,
idToken: data.id_token,
idpType,
csrf: null,
apiSessionId: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CloudAuthIdpType } from 'src/modules/cloud/auth/models';
export interface ICloudApiCredentials {
accessToken?: string;
refreshToken?: string;
idToken?: string;
idpType?: CloudAuthIdpType;
apiSessionId?: string;
csrf?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,26 @@ const getHeadersTests = [
input: { csrf: 'csrf-token' },
expected: { ...mockDefaultCloudApiHeaders, 'x-csrf-token': 'csrf-token' },
},
{
input: { idToken: 'id-token-value' },
expected: {
...mockDefaultCloudApiHeaders,
'Sm-Id-Token': 'id-token-value',
},
},
{
input: {
accessToken: 'jwt-token',
idToken: 'id-token-value',
csrf: 'csrf-token',
},
expected: {
...mockDefaultCloudApiHeaders,
authorization: 'Bearer jwt-token',
'x-csrf-token': 'csrf-token',
'Sm-Id-Token': 'id-token-value',
},
},
];

const mockedResult = 'mockedResult';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export class CloudApiProvider {
headers['x-csrf-token'] = credentials.csrf;
}

if (credentials?.idToken) {
headers['Sm-Id-Token'] = credentials.idToken;
}

return {
headers,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export class CloudSession {
@Expose()
refreshToken?: string;

@Expose()
idToken?: string;

@Expose()
idpType?: CloudAuthIdpType;

Expand Down
Loading