import { mock, MockProxy } from "jest-mock-extended"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { AppIdService } from "@bitwarden/common/abstractions/appId.service"; import { CryptoService } from "@bitwarden/common/abstractions/crypto.service"; import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service"; import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service"; import { LogService } from "@bitwarden/common/abstractions/log.service"; import { MessagingService } from "@bitwarden/common/abstractions/messaging.service"; import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { StateService } from "@bitwarden/common/abstractions/state.service"; import { TokenService } from "@bitwarden/common/abstractions/token.service"; import { TwoFactorService } from "@bitwarden/common/abstractions/twoFactor.service"; import { UserApiLogInStrategy } from "@bitwarden/common/misc/logInStrategies/user-api-login.strategy"; import { Utils } from "@bitwarden/common/misc/utils"; import { UserApiLogInCredentials } from "@bitwarden/common/models/domain/log-in-credentials"; import { identityTokenResponseFactory } from "./logIn.strategy.spec"; describe("UserApiLogInStrategy", () => { let cryptoService: MockProxy; let apiService: MockProxy; let tokenService: MockProxy; let appIdService: MockProxy; let platformUtilsService: MockProxy; let messagingService: MockProxy; let logService: MockProxy; let stateService: MockProxy; let twoFactorService: MockProxy; let keyConnectorService: MockProxy; let environmentService: MockProxy; let apiLogInStrategy: UserApiLogInStrategy; let credentials: UserApiLogInCredentials; const deviceId = Utils.newGuid(); const keyConnectorUrl = "KEY_CONNECTOR_URL"; const apiClientId = "API_CLIENT_ID"; const apiClientSecret = "API_CLIENT_SECRET"; beforeEach(async () => { cryptoService = mock(); apiService = mock(); tokenService = mock(); appIdService = mock(); platformUtilsService = mock(); messagingService = mock(); logService = mock(); stateService = mock(); twoFactorService = mock(); keyConnectorService = mock(); environmentService = mock(); appIdService.getAppId.mockResolvedValue(deviceId); tokenService.getTwoFactorToken.mockResolvedValue(null); tokenService.decodeToken.mockResolvedValue({}); apiLogInStrategy = new UserApiLogInStrategy( cryptoService, apiService, tokenService, appIdService, platformUtilsService, messagingService, logService, stateService, twoFactorService, environmentService, keyConnectorService ); credentials = new UserApiLogInCredentials(apiClientId, apiClientSecret); }); it("sends api key credentials to the server", async () => { apiService.postIdentityToken.mockResolvedValue(identityTokenResponseFactory()); await apiLogInStrategy.logIn(credentials); expect(apiService.postIdentityToken).toHaveBeenCalledWith( expect.objectContaining({ clientId: apiClientId, clientSecret: apiClientSecret, device: expect.objectContaining({ identifier: deviceId, }), twoFactor: expect.objectContaining({ provider: null, token: null, }), }) ); }); it("sets the local environment after a successful login", async () => { apiService.postIdentityToken.mockResolvedValue(identityTokenResponseFactory()); await apiLogInStrategy.logIn(credentials); expect(stateService.setApiKeyClientId).toHaveBeenCalledWith(apiClientId); expect(stateService.setApiKeyClientSecret).toHaveBeenCalledWith(apiClientSecret); expect(stateService.addAccount).toHaveBeenCalled(); }); it("gets and sets the Key Connector key from environmentUrl", async () => { const tokenResponse = identityTokenResponseFactory(); tokenResponse.apiUseKeyConnector = true; apiService.postIdentityToken.mockResolvedValue(tokenResponse); environmentService.getKeyConnectorUrl.mockReturnValue(keyConnectorUrl); await apiLogInStrategy.logIn(credentials); expect(keyConnectorService.getAndSetKey).toHaveBeenCalledWith(keyConnectorUrl); }); });