1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-25 12:15:18 +01:00

Auth/PM-7092 - Fix CLI login via API key not working due to TokenService changes (#8499)

* PM-7092 - Fix CLI login via API key not working (it apparently receives an undefined refresh token which was rejected by setTokens)

* PM-7092 - Fix base login strategy tests

* PM-7092 - per discucssion with jake, refactor setTokens to accept optional refresh token instead of exposing setRefreshToken as public.
This commit is contained in:
Jared Snider 2024-03-27 17:46:56 -04:00 committed by GitHub
parent d9bec7f984
commit 8cdc94076e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 26 additions and 25 deletions

View File

@ -186,9 +186,9 @@ describe("LoginStrategy", () => {
expect(tokenService.setTokens).toHaveBeenCalledWith(
accessToken,
refreshToken,
mockVaultTimeoutAction,
mockVaultTimeout,
refreshToken,
);
expect(stateService.addAccount).toHaveBeenCalledWith(

View File

@ -182,9 +182,9 @@ export abstract class LoginStrategy {
// User id will be derived from the access token.
await this.tokenService.setTokens(
tokenResponse.accessToken,
tokenResponse.refreshToken,
vaultTimeoutAction as VaultTimeoutAction,
vaultTimeout,
tokenResponse.refreshToken, // Note: CLI login via API key sends undefined for refresh token.
);
await this.stateService.addAccount(

View File

@ -10,17 +10,18 @@ export abstract class TokenService {
* Note 2: this method also enforces always setting the access token and the refresh token together as
* we can retrieve the user id required to set the refresh token from the access token for efficiency.
* @param accessToken The access token to set.
* @param refreshToken The refresh token to set.
* @param clientIdClientSecret The API Key Client ID and Client Secret to set.
* @param vaultTimeoutAction The action to take when the vault times out.
* @param vaultTimeout The timeout for the vault.
* @param refreshToken The optional refresh token to set. Note: this is undefined when using the CLI Login Via API Key flow
* @param clientIdClientSecret The API Key Client ID and Client Secret to set.
*
* @returns A promise that resolves when the tokens have been set.
*/
setTokens: (
accessToken: string,
refreshToken: string,
vaultTimeoutAction: VaultTimeoutAction,
vaultTimeout: number | null,
refreshToken?: string,
clientIdClientSecret?: [string, string],
) => Promise<void>;

View File

@ -991,6 +991,7 @@ describe("TokenService", () => {
refreshToken,
VaultTimeoutAction.Lock,
null,
null,
);
// Assert
await expect(result).rejects.toThrow("User id not found. Cannot save refresh token.");
@ -1854,7 +1855,7 @@ describe("TokenService", () => {
// Act
// Note: passing a valid access token so that a valid user id can be determined from the access token
await tokenService.setTokens(accessTokenJwt, refreshToken, vaultTimeoutAction, vaultTimeout, [
await tokenService.setTokens(accessTokenJwt, vaultTimeoutAction, vaultTimeout, refreshToken, [
clientId,
clientSecret,
]);
@ -1901,7 +1902,7 @@ describe("TokenService", () => {
tokenService.setClientSecret = jest.fn();
// Act
await tokenService.setTokens(accessTokenJwt, refreshToken, vaultTimeoutAction, vaultTimeout);
await tokenService.setTokens(accessTokenJwt, vaultTimeoutAction, vaultTimeout, refreshToken);
// Assert
expect((tokenService as any)._setAccessToken).toHaveBeenCalledWith(
@ -1933,9 +1934,9 @@ describe("TokenService", () => {
// Act
const result = tokenService.setTokens(
accessToken,
refreshToken,
vaultTimeoutAction,
vaultTimeout,
refreshToken,
);
// Assert
@ -1952,32 +1953,27 @@ describe("TokenService", () => {
// Act
const result = tokenService.setTokens(
accessToken,
refreshToken,
vaultTimeoutAction,
vaultTimeout,
refreshToken,
);
// Assert
await expect(result).rejects.toThrow("Access token and refresh token are required.");
await expect(result).rejects.toThrow("Access token is required.");
});
it("should throw an error if the refresh token is missing", async () => {
it("should not throw an error if the refresh token is missing and it should just not set it", async () => {
// Arrange
const accessToken = "accessToken";
const refreshToken: string = null;
const vaultTimeoutAction = VaultTimeoutAction.Lock;
const vaultTimeout = 30;
(tokenService as any).setRefreshToken = jest.fn();
// Act
const result = tokenService.setTokens(
accessToken,
refreshToken,
vaultTimeoutAction,
vaultTimeout,
);
await tokenService.setTokens(accessTokenJwt, vaultTimeoutAction, vaultTimeout, refreshToken);
// Assert
await expect(result).rejects.toThrow("Access token and refresh token are required.");
expect((tokenService as any).setRefreshToken).not.toHaveBeenCalled();
});
});

View File

@ -149,13 +149,13 @@ export class TokenService implements TokenServiceAbstraction {
async setTokens(
accessToken: string,
refreshToken: string,
vaultTimeoutAction: VaultTimeoutAction,
vaultTimeout: number | null,
refreshToken?: string,
clientIdClientSecret?: [string, string],
): Promise<void> {
if (!accessToken || !refreshToken) {
throw new Error("Access token and refresh token are required.");
if (!accessToken) {
throw new Error("Access token is required.");
}
// get user id the access token
@ -166,7 +166,11 @@ export class TokenService implements TokenServiceAbstraction {
}
await this._setAccessToken(accessToken, vaultTimeoutAction, vaultTimeout, userId);
if (refreshToken) {
await this.setRefreshToken(refreshToken, vaultTimeoutAction, vaultTimeout, userId);
}
if (clientIdClientSecret != null) {
await this.setClientId(clientIdClientSecret[0], vaultTimeoutAction, vaultTimeout, userId);
await this.setClientSecret(clientIdClientSecret[1], vaultTimeoutAction, vaultTimeout, userId);

View File

@ -1780,9 +1780,9 @@ export class ApiService implements ApiServiceAbstraction {
await this.tokenService.setTokens(
tokenResponse.accessToken,
tokenResponse.refreshToken,
vaultTimeoutAction as VaultTimeoutAction,
vaultTimeout,
tokenResponse.refreshToken,
);
} else {
const error = await this.handleError(response, true, true);

View File

@ -52,7 +52,7 @@ export class VaultTimeoutSettingsService implements VaultTimeoutSettingsServiceA
await this.stateService.setVaultTimeoutAction(action);
await this.tokenService.setTokens(accessToken, refreshToken, action, timeout, [
await this.tokenService.setTokens(accessToken, action, timeout, refreshToken, [
clientId,
clientSecret,
]);