diff --git a/libs/auth/src/angular/login-via-auth-request/README.md b/libs/auth/src/angular/login-via-auth-request/README.md index 3396ba8698b..d1c4ddf3f0a 100644 --- a/libs/auth/src/angular/login-via-auth-request/README.md +++ b/libs/auth/src/angular/login-via-auth-request/README.md @@ -13,16 +13,9 @@ ## Standard Auth Request Flows -### Flow 1: Unauthed user requests approval from device; Approving device has a masterKey in memory +### Flow 1: This flow was removed -1. Unauthed user clicks "Login with device" -2. Navigates to `/login-with-device` which creates a `StandardAuthRequest` -3. Receives approval from a device with authRequestPublicKey(masterKey) -4. Decrypts masterKey -5. Decrypts userKey -6. Proceeds to vault - -### Flow 2: Unauthed user requests approval from device; Approving device does NOT have a masterKey in memory +### Flow 2: Unauthed user requests approval from device; Approving device does NOT need to have a masterKey in memory 1. Unauthed user clicks "Login with device" 2. Navigates to `/login-with-device` which creates a `StandardAuthRequest` @@ -33,28 +26,18 @@ **Note:** This flow is an uncommon scenario and relates to TDE off-boarding. The following describes how a user could get into this flow: -1. An SSO TD user logs into a device via an Admin auth request approval, therefore this device does NOT have a masterKey +1. An SSO TD user logs into a device via an Admin auth request approval, therefore this device does NOT need to have a masterKey in memory 2. The org admin: - Changes the member decryption options from "Trusted devices" to "Master password" AND - Turns off the "Require single sign-on authentication" policy 3. On another device, the user clicks "Login with device", which they can do because the org no longer requires SSO -4. The user approves from the device they had previously logged into with SSO TD, which does NOT have a masterKey in +4. The user approves from the device they had previously logged into with SSO TD, which does NOT need to have a masterKey in memory -### Flow 3: Authed SSO TD user requests approval from device; Approving device has a masterKey in memory +### Flow 3: This flow was removed -1. SSO TD user authenticates via SSO -2. Navigates to `/login-initiated` -3. Clicks "Approve from your other device" -4. Navigates to `/login-with-device` which creates a `StandardAuthRequest` -5. Receives approval from device with authRequestPublicKey(masterKey) -6. Decrypts masterKey -7. Decrypts userKey -8. Establishes trust (if required) -9. Proceeds to vault - -### Flow 4: Authed SSO TD user requests approval from device; Approving device does NOT have a masterKey in memory +### Flow 4: Authed SSO TD user requests approval from device; Approving device does NOT need to have a masterKey in memory 1. SSO TD user authenticates via SSO 2. Navigates to `/login-initiated` @@ -89,9 +72,7 @@ userKey. This is how admins are able to send over the authRequestPublicKey(userK | Flow | Auth Status | Clicks Button [active route] | Navigates to | Approving device has masterKey in memory\* | | --------------- | ----------- | ----------------------------------------------------- | --------------------------- | ------------------------------------------------- | -| Standard Flow 1 | unauthed | "Login with device" [`/login`] | `/login-with-device` | yes | | Standard Flow 2 | unauthed | "Login with device" [`/login`] | `/login-with-device` | no | -| Standard Flow 3 | authed | "Approve from your other device" [`/login-initiated`] | `/login-with-device` | yes | | Standard Flow 4 | authed | "Approve from your other device" [`/login-initiated`] | `/login-with-device` | no | | Admin Flow | authed | "Request admin approval"
[`/login-initiated`] | `/admin-approval-requested` | NA - admin requests always send encrypted userKey | diff --git a/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts b/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts index fc91f220138..c7046d39022 100644 --- a/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts +++ b/libs/auth/src/angular/login-via-auth-request/login-via-auth-request.component.ts @@ -605,10 +605,10 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { if (authRequestResponse.requestApproved) { const userHasAuthenticatedViaSSO = this.authStatus === AuthenticationStatus.Locked; if (userHasAuthenticatedViaSSO) { - // [Standard Flow 3-4] Handle authenticated SSO TD user flows + // [Standard Flow 4] Handle authenticated SSO TD user flows return await this.handleAuthenticatedFlows(authRequestResponse); } else { - // [Standard Flow 1-2] Handle unauthenticated user flows + // [Standard Flow 2] Handle unauthenticated user flows return await this.handleUnauthenticatedFlows(authRequestResponse, requestId); } } @@ -629,7 +629,7 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { } private async handleAuthenticatedFlows(authRequestResponse: AuthRequestResponse) { - // [Standard Flow 3-4] Handle authenticated SSO TD user flows + // [Standard Flow 4] Handle authenticated SSO TD user flows const userId = (await firstValueFrom(this.accountService.activeAccount$))?.id; if (!userId) { this.logService.error( @@ -654,7 +654,7 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { authRequestResponse: AuthRequestResponse, requestId: string, ) { - // [Standard Flow 1-2] Handle unauthenticated user flows + // [Standard Flow 2] Handle unauthenticated user flows const authRequestLoginCredentials = await this.buildAuthRequestLoginCredentials( requestId, authRequestResponse, @@ -679,27 +679,12 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { privateKey: Uint8Array, userId: UserId, ): Promise { - /** - * [Flow Type Detection] - * We determine the type of `key` based on the presence or absence of `masterPasswordHash`: - * - If `masterPasswordHash` exists: Standard Flow 1 or 3 (device has masterKey) - * - If no `masterPasswordHash`: Standard Flow 2, 4, or Admin Flow (device sends userKey) - */ - if (authRequestResponse.masterPasswordHash) { - // [Standard Flow 1 or 3] Device has masterKey - await this.authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash( - authRequestResponse, - privateKey, - userId, - ); - } else { - // [Standard Flow 2, 4, or Admin Flow] Device sends userKey - await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey( - authRequestResponse, - privateKey, - userId, - ); - } + // [Standard Flow 2, 4, or Admin Flow] Device sends userKey + await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey( + authRequestResponse, + privateKey, + userId, + ); // [Admin Flow Cleanup] Clear one-time use admin auth request // clear the admin auth request from state so it cannot be used again (it's a one time use) @@ -758,43 +743,13 @@ export class LoginViaAuthRequestComponent implements OnInit, OnDestroy { /** * See verifyAndHandleApprovedAuthReq() for flow details. - * - * We determine the type of `key` based on the presence or absence of `masterPasswordHash`: - * - If `masterPasswordHash` has a value, we receive the `key` as an authRequestPublicKey(masterKey) [plus we have authRequestPublicKey(masterPasswordHash)] - * - If `masterPasswordHash` does not have a value, we receive the `key` as an authRequestPublicKey(userKey) */ - if (authRequestResponse.masterPasswordHash) { - // ...in Standard Auth Request Flow 1 - const { masterKey, masterKeyHash } = - await this.authRequestService.decryptPubKeyEncryptedMasterKeyAndHash( - authRequestResponse.key, - authRequestResponse.masterPasswordHash, - this.authRequestKeyPair.privateKey, - ); - - return new AuthRequestLoginCredentials( - this.email, - this.accessCode, - requestId, - null, // no userKey - masterKey, - masterKeyHash, - ); - } else { - // ...in Standard Auth Request Flow 2 - const userKey = await this.authRequestService.decryptPubKeyEncryptedUserKey( - authRequestResponse.key, - this.authRequestKeyPair.privateKey, - ); - return new AuthRequestLoginCredentials( - this.email, - this.accessCode, - requestId, - userKey, - null, // no masterKey - null, // no masterKeyHash - ); - } + // ...in Standard Auth Request Flow 2 + const userKey = await this.authRequestService.decryptPubKeyEncryptedUserKey( + authRequestResponse.key, + this.authRequestKeyPair.privateKey, + ); + return new AuthRequestLoginCredentials(this.email, this.accessCode, requestId, userKey); } private async clearExistingAdminAuthRequestAndStartNewRequest(userId: UserId) { diff --git a/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts b/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts index 1077bc024e9..04128768759 100644 --- a/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts +++ b/libs/auth/src/common/abstractions/auth-request.service.abstraction.ts @@ -4,7 +4,7 @@ import { AdminAuthRequestStorable } from "@bitwarden/common/auth/models/domain/a import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response"; import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response"; import { UserId } from "@bitwarden/common/types/guid"; -import { UserKey, MasterKey } from "@bitwarden/common/types/key"; +import { UserKey } from "@bitwarden/common/types/key"; export abstract class AuthRequestServiceAbstraction { /** Emits an auth request id when an auth request has been approved. */ @@ -75,17 +75,6 @@ export abstract class AuthRequestServiceAbstraction { authReqPrivateKey: Uint8Array, userId: UserId, ): Promise; - /** - * Sets the `MasterKey` and `MasterKeyHash` from an auth request. Auth request must have a `MasterKey` and `MasterKeyHash`. - * @param authReqResponse The auth request. - * @param authReqPrivateKey The private key corresponding to the public key sent in the auth request. - * @param userId The ID of the user for whose account we will set the keys. - */ - abstract setKeysAfterDecryptingSharedMasterKeyAndHash( - authReqResponse: AuthRequestResponse, - authReqPrivateKey: Uint8Array, - userId: UserId, - ): Promise; /** * Decrypts a `UserKey` from a public key encrypted `UserKey`. * @param pubKeyEncryptedUserKey The public key encrypted `UserKey`. @@ -96,18 +85,6 @@ export abstract class AuthRequestServiceAbstraction { pubKeyEncryptedUserKey: string, privateKey: Uint8Array, ): Promise; - /** - * Decrypts a `MasterKey` and `MasterKeyHash` from a public key encrypted `MasterKey` and `MasterKeyHash`. - * @param pubKeyEncryptedMasterKey The public key encrypted `MasterKey`. - * @param pubKeyEncryptedMasterKeyHash The public key encrypted `MasterKeyHash`. - * @param privateKey The private key corresponding to the public key used to encrypt the `MasterKey` and `MasterKeyHash`. - * @returns The decrypted `MasterKey` and `MasterKeyHash`. - */ - abstract decryptPubKeyEncryptedMasterKeyAndHash( - pubKeyEncryptedMasterKey: string, - pubKeyEncryptedMasterKeyHash: string, - privateKey: Uint8Array, - ): Promise<{ masterKey: MasterKey; masterKeyHash: string }>; /** * Handles incoming auth request push server notifications. diff --git a/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts index 275f2d97aa4..b07dc1202de 100644 --- a/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/auth-request-login.strategy.spec.ts @@ -26,7 +26,7 @@ import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/sym import { makeEncString, FakeAccountService, mockAccountServiceWith } from "@bitwarden/common/spec"; import { CsprngArray } from "@bitwarden/common/types/csprng"; import { UserId } from "@bitwarden/common/types/guid"; -import { MasterKey, UserKey } from "@bitwarden/common/types/key"; +import { UserKey } from "@bitwarden/common/types/key"; import { KdfConfigService, KeyService } from "@bitwarden/key-management"; import { InternalUserDecryptionOptionsServiceAbstraction } from "../abstractions/user-decryption-options.service.abstraction"; @@ -73,11 +73,7 @@ describe("AuthRequestLoginStrategy", () => { const email = "EMAIL"; const accessCode = "ACCESS_CODE"; const authRequestId = "AUTH_REQUEST_ID"; - const decMasterKey = new SymmetricCryptoKey( - new Uint8Array(64).buffer as CsprngArray, - ) as MasterKey; const decUserKey = new SymmetricCryptoKey(new Uint8Array(64).buffer as CsprngArray) as UserKey; - const decMasterKeyHash = "LOCAL_PASSWORD_HASH"; beforeEach(async () => { keyService = mock(); @@ -150,42 +146,6 @@ describe("AuthRequestLoginStrategy", () => { ); }); - it("sets keys after a successful authentication when masterKey and masterKeyHash provided in login credentials", async () => { - credentials = new AuthRequestLoginCredentials( - email, - accessCode, - authRequestId, - null, - decMasterKey, - decMasterKeyHash, - ); - - const masterKey = new SymmetricCryptoKey(new Uint8Array(64).buffer as CsprngArray) as MasterKey; - const userKey = new SymmetricCryptoKey(new Uint8Array(64).buffer as CsprngArray) as UserKey; - - masterPasswordService.masterKeySubject.next(masterKey); - masterPasswordService.mock.decryptUserKeyWithMasterKey.mockResolvedValue(userKey); - tokenService.decodeAccessToken.mockResolvedValue({ sub: mockUserId }); - - await authRequestLoginStrategy.logIn(credentials); - - expect(masterPasswordService.mock.setMasterKey).toHaveBeenCalledWith(masterKey, mockUserId); - expect(masterPasswordService.mock.setMasterKeyHash).toHaveBeenCalledWith( - decMasterKeyHash, - mockUserId, - ); - expect(masterPasswordService.mock.setMasterKeyEncryptedUserKey).toHaveBeenCalledWith( - tokenResponse.key, - mockUserId, - ); - expect(keyService.setUserKey).toHaveBeenCalledWith(userKey, mockUserId); - expect(deviceTrustService.trustDeviceIfRequired).toHaveBeenCalled(); - expect(accountCryptographicStateService.setAccountCryptographicState).toHaveBeenCalledWith( - { V1: { private_key: tokenResponse.privateKey } }, - mockUserId, - ); - }); - it("sets keys after a successful authentication when only userKey provided in login credentials", async () => { // Initialize credentials with only userKey credentials = new AuthRequestLoginCredentials( @@ -193,8 +153,6 @@ describe("AuthRequestLoginStrategy", () => { accessCode, authRequestId, decUserKey, // Pass userKey - null, // No masterKey - null, // No masterKeyHash ); // Call logIn @@ -240,7 +198,6 @@ describe("AuthRequestLoginStrategy", () => { }; apiService.postIdentityToken.mockResolvedValue(tokenResponse); - masterPasswordService.masterKeySubject.next(decMasterKey); masterPasswordService.mock.decryptUserKeyWithMasterKey.mockResolvedValue(decUserKey); await authRequestLoginStrategy.logIn(credentials); diff --git a/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts b/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts index 66b9ee83919..1f3eaf7c164 100644 --- a/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/auth-request-login.strategy.ts @@ -72,20 +72,7 @@ export class AuthRequestLoginStrategy extends LoginStrategy { } protected override async setMasterKey(response: IdentityTokenResponse, userId: UserId) { - const authRequestCredentials = this.cache.value.authRequestCredentials; - if ( - authRequestCredentials.decryptedMasterKey && - authRequestCredentials.decryptedMasterKeyHash - ) { - await this.masterPasswordService.setMasterKey( - authRequestCredentials.decryptedMasterKey, - userId, - ); - await this.masterPasswordService.setMasterKeyHash( - authRequestCredentials.decryptedMasterKeyHash, - userId, - ); - } + // This login strategy does not use a master key } protected override async setUserKey( diff --git a/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts b/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts index 4f0a6bbf73f..f7a97baba0a 100644 --- a/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts +++ b/libs/auth/src/common/login-strategies/sso-login.strategy.spec.ts @@ -416,24 +416,6 @@ describe("SsoLoginStrategy", () => { ); }); - it("sets the user key using master key and hash from approved admin request if exists", async () => { - apiService.postIdentityToken.mockResolvedValue(tokenResponse); - keyService.hasUserKey.mockResolvedValue(true); - const adminAuthResponse = { - id: "1", - publicKey: "PRIVATE" as any, - key: "KEY" as any, - masterPasswordHash: "HASH" as any, - requestApproved: true, - }; - apiService.getAuthRequest.mockResolvedValue(adminAuthResponse as AuthRequestResponse); - - await ssoLoginStrategy.logIn(credentials); - - expect(authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash).toHaveBeenCalled(); - expect(deviceTrustService.decryptUserKeyWithDeviceKey).not.toHaveBeenCalled(); - }); - it("sets the user key from approved admin request if exists", async () => { apiService.postIdentityToken.mockResolvedValue(tokenResponse); keyService.hasUserKey.mockResolvedValue(true); @@ -475,9 +457,6 @@ describe("SsoLoginStrategy", () => { await ssoLoginStrategy.logIn(credentials); expect(authRequestService.clearAdminAuthRequest).toHaveBeenCalled(); - expect( - authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash, - ).not.toHaveBeenCalled(); expect(authRequestService.setUserKeyAfterDecryptingSharedUserKey).not.toHaveBeenCalled(); expect(deviceTrustService.trustDeviceIfRequired).not.toHaveBeenCalled(); }); diff --git a/libs/auth/src/common/login-strategies/sso-login.strategy.ts b/libs/auth/src/common/login-strategies/sso-login.strategy.ts index 6a57d11e29d..9c889d9d460 100644 --- a/libs/auth/src/common/login-strategies/sso-login.strategy.ts +++ b/libs/auth/src/common/login-strategies/sso-login.strategy.ts @@ -239,23 +239,11 @@ export class SsoLoginStrategy extends LoginStrategy { } if (adminAuthReqResponse?.requestApproved) { - // if masterPasswordHash has a value, we will always receive authReqResponse.key - // as authRequestPublicKey(masterKey) + authRequestPublicKey(masterPasswordHash) - if (adminAuthReqResponse.masterPasswordHash) { - await this.authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash( - adminAuthReqResponse, - adminAuthReqStorable.privateKey, - userId, - ); - } else { - // if masterPasswordHash is null, we will always receive authReqResponse.key - // as authRequestPublicKey(userKey) - await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey( - adminAuthReqResponse, - adminAuthReqStorable.privateKey, - userId, - ); - } + await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey( + adminAuthReqResponse, + adminAuthReqStorable.privateKey, + userId, + ); if (await this.keyService.hasUserKey(userId)) { // Now that we have a decrypted user key in memory, we can check if we diff --git a/libs/auth/src/common/models/domain/login-credentials.ts b/libs/auth/src/common/models/domain/login-credentials.ts index 96ee88945eb..608b36e908b 100644 --- a/libs/auth/src/common/models/domain/login-credentials.ts +++ b/libs/auth/src/common/models/domain/login-credentials.ts @@ -7,7 +7,7 @@ import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication- import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request"; import { WebAuthnLoginAssertionResponseRequest } from "@bitwarden/common/auth/services/webauthn-login/request/webauthn-login-assertion-response.request"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; -import { UserKey, MasterKey } from "@bitwarden/common/types/key"; +import { UserKey } from "@bitwarden/common/types/key"; export class PasswordLoginCredentials { readonly type = AuthenticationType.Password; @@ -54,8 +54,6 @@ export class AuthRequestLoginCredentials { public accessCode: string, public authRequestId: string, public decryptedUserKey: UserKey | null, - public decryptedMasterKey: MasterKey | null, - public decryptedMasterKeyHash: string | null, public twoFactor?: TokenTwoFactorRequest, ) {} @@ -66,8 +64,6 @@ export class AuthRequestLoginCredentials { json.accessCode, json.authRequestId, null, - null, - json.decryptedMasterKeyHash, json.twoFactor ? new TokenTwoFactorRequest( json.twoFactor.provider, @@ -78,7 +74,6 @@ export class AuthRequestLoginCredentials { ), { decryptedUserKey: SymmetricCryptoKey.fromJSON(json.decryptedUserKey) as UserKey, - decryptedMasterKey: SymmetricCryptoKey.fromJSON(json.decryptedMasterKey) as MasterKey, }, ); } diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts index 8cb0cc279ae..a3f79f45ad5 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.spec.ts @@ -13,7 +13,7 @@ import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.ser import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { StateProvider } from "@bitwarden/common/platform/state"; import { UserId } from "@bitwarden/common/types/guid"; -import { MasterKey, UserKey } from "@bitwarden/common/types/key"; +import { UserKey } from "@bitwarden/common/types/key"; import { newGuid } from "@bitwarden/guid"; import { KeyService } from "@bitwarden/key-management"; @@ -154,60 +154,6 @@ describe("AuthRequestService", () => { }); }); - describe("setKeysAfterDecryptingSharedMasterKeyAndHash", () => { - it("decrypts and sets master key and hash and user key when given valid auth request response and private key", async () => { - // Arrange - const mockAuthReqResponse = { - key: "authReqPublicKeyEncryptedMasterKey", - masterPasswordHash: "authReqPublicKeyEncryptedMasterKeyHash", - } as AuthRequestResponse; - - const mockDecryptedMasterKey = {} as MasterKey; - const mockDecryptedMasterKeyHash = "mockDecryptedMasterKeyHash"; - const mockDecryptedUserKey = {} as UserKey; - - jest.spyOn(sut, "decryptPubKeyEncryptedMasterKeyAndHash").mockResolvedValueOnce({ - masterKey: mockDecryptedMasterKey, - masterKeyHash: mockDecryptedMasterKeyHash, - }); - - masterPasswordService.masterKeySubject.next(undefined); - masterPasswordService.masterKeyHashSubject.next(undefined); - masterPasswordService.mock.decryptUserKeyWithMasterKey.mockResolvedValue( - mockDecryptedUserKey, - ); - keyService.setUserKey.mockResolvedValueOnce(undefined); - - // Act - await sut.setKeysAfterDecryptingSharedMasterKeyAndHash( - mockAuthReqResponse, - mockPrivateKey, - mockUserId, - ); - - // Assert - expect(sut.decryptPubKeyEncryptedMasterKeyAndHash).toBeCalledWith( - mockAuthReqResponse.key, - mockAuthReqResponse.masterPasswordHash, - mockPrivateKey, - ); - expect(masterPasswordService.mock.setMasterKey).toHaveBeenCalledWith( - mockDecryptedMasterKey, - mockUserId, - ); - expect(masterPasswordService.mock.setMasterKeyHash).toHaveBeenCalledWith( - mockDecryptedMasterKeyHash, - mockUserId, - ); - expect(masterPasswordService.mock.decryptUserKeyWithMasterKey).toHaveBeenCalledWith( - mockDecryptedMasterKey, - mockUserId, - undefined, - ); - expect(keyService.setUserKey).toHaveBeenCalledWith(mockDecryptedUserKey, mockUserId); - }); - }); - describe("decryptAuthReqPubKeyEncryptedUserKey", () => { it("returns a decrypted user key when given valid public key encrypted user key and an auth req private key", async () => { // Arrange diff --git a/libs/auth/src/common/services/auth-request/auth-request.service.ts b/libs/auth/src/common/services/auth-request/auth-request.service.ts index ba4b9eaf174..f1ff8416d11 100644 --- a/libs/auth/src/common/services/auth-request/auth-request.service.ts +++ b/libs/auth/src/common/services/auth-request/auth-request.service.ts @@ -16,14 +16,13 @@ import { ListResponse } from "@bitwarden/common/models/response/list.response"; import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { Utils } from "@bitwarden/common/platform/misc/utils"; -import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key"; import { AUTH_REQUEST_DISK_LOCAL, StateProvider, UserKeyDefinition, } from "@bitwarden/common/platform/state"; import { UserId } from "@bitwarden/common/types/guid"; -import { MasterKey, UserKey } from "@bitwarden/common/types/key"; +import { UserKey } from "@bitwarden/common/types/key"; import { KeyService } from "@bitwarden/key-management"; import { AuthRequestApiServiceAbstraction } from "../../abstractions/auth-request-api.service"; @@ -163,27 +162,6 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { await this.keyService.setUserKey(userKey, userId); } - async setKeysAfterDecryptingSharedMasterKeyAndHash( - authReqResponse: AuthRequestResponse, - authReqPrivateKey: Uint8Array, - userId: UserId, - ) { - const { masterKey, masterKeyHash } = await this.decryptPubKeyEncryptedMasterKeyAndHash( - authReqResponse.key, - authReqResponse.masterPasswordHash, - authReqPrivateKey, - ); - - // Decrypt and set user key in state - const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey, userId); - - // Set masterKey + masterKeyHash in state after decryption (in case decryption fails) - await this.masterPasswordService.setMasterKey(masterKey, userId); - await this.masterPasswordService.setMasterKeyHash(masterKeyHash, userId); - - await this.keyService.setUserKey(userKey, userId); - } - // Decryption helpers async decryptPubKeyEncryptedUserKey( pubKeyEncryptedUserKey: string, @@ -197,30 +175,6 @@ export class AuthRequestService implements AuthRequestServiceAbstraction { return decryptedUserKey as UserKey; } - async decryptPubKeyEncryptedMasterKeyAndHash( - pubKeyEncryptedMasterKey: string, - pubKeyEncryptedMasterKeyHash: string, - privateKey: Uint8Array, - ): Promise<{ masterKey: MasterKey; masterKeyHash: string }> { - const decryptedMasterKeyArrayBuffer = await this.encryptService.rsaDecrypt( - new EncString(pubKeyEncryptedMasterKey), - privateKey, - ); - - const decryptedMasterKeyHashArrayBuffer = await this.encryptService.rsaDecrypt( - new EncString(pubKeyEncryptedMasterKeyHash), - privateKey, - ); - - const masterKey = new SymmetricCryptoKey(decryptedMasterKeyArrayBuffer) as MasterKey; - const masterKeyHash = Utils.fromBufferToUtf8(decryptedMasterKeyHashArrayBuffer); - - return { - masterKey, - masterKeyHash, - }; - } - sendAuthRequestPushNotification(notification: AuthRequestPushNotification): void { if (notification.id != null) { this.authRequestPushNotificationSubject.next(notification.id); diff --git a/libs/auth/src/common/services/login-strategies/login-strategy.state.spec.ts b/libs/auth/src/common/services/login-strategies/login-strategy.state.spec.ts index 32c5fdcc4d5..195ae0dd721 100644 --- a/libs/auth/src/common/services/login-strategies/login-strategy.state.spec.ts +++ b/libs/auth/src/common/services/login-strategies/login-strategy.state.spec.ts @@ -93,8 +93,6 @@ describe("LOGIN_STRATEGY_CACHE_KEY", () => { "ACCESS_CODE", "AUTH_REQUEST_ID", new SymmetricCryptoKey(new Uint8Array(64)) as UserKey, - new SymmetricCryptoKey(new Uint8Array(64)) as MasterKey, - "MASTER_KEY_HASH", ); const result = sut.deserializer(JSON.parse(JSON.stringify(actual))); diff --git a/libs/common/src/auth/models/response/auth-request.response.ts b/libs/common/src/auth/models/response/auth-request.response.ts index 94c65000919..8d02e161e68 100644 --- a/libs/common/src/auth/models/response/auth-request.response.ts +++ b/libs/common/src/auth/models/response/auth-request.response.ts @@ -11,8 +11,7 @@ export class AuthRequestResponse extends BaseResponse { requestDeviceIdentifier: string; requestIpAddress: string; requestCountryName: string; - key: string; // could be either an encrypted MasterKey or an encrypted UserKey - masterPasswordHash: string; // if hash is present, the `key` above is an encrypted MasterKey (else `key` is an encrypted UserKey) + key: string; // Auth-request public-key encrypted user-key. Note: No sender authenticity provided! creationDate: string; requestApproved?: boolean; responseDate?: string; @@ -30,7 +29,6 @@ export class AuthRequestResponse extends BaseResponse { this.requestIpAddress = this.getResponseProperty("RequestIpAddress"); this.requestCountryName = this.getResponseProperty("RequestCountryName"); this.key = this.getResponseProperty("Key"); - this.masterPasswordHash = this.getResponseProperty("MasterPasswordHash"); this.creationDate = this.getResponseProperty("CreationDate"); this.requestApproved = this.getResponseProperty("RequestApproved"); this.responseDate = this.getResponseProperty("ResponseDate"); diff --git a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts index 03cfd173a4d..ed1458b704e 100644 --- a/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts +++ b/libs/common/src/key-management/crypto/abstractions/encrypt.service.ts @@ -161,13 +161,6 @@ export abstract class EncryptService { decapsulationKey: Uint8Array, ): Promise; - /** - * @deprecated Use @see {@link decapsulateKeyUnsigned} instead - * @param data - The ciphertext to decrypt - * @param privateKey - The privateKey to decrypt with - */ - abstract rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise; - /** * Generates a base64-encoded hash of the given value * @param value The value to hash diff --git a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts index b14211b5b72..5fa5fa5eea0 100644 --- a/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts +++ b/libs/common/src/key-management/crypto/services/encrypt.service.implementation.ts @@ -219,24 +219,4 @@ export class EncryptServiceImplementation implements EncryptService { ); return new SymmetricCryptoKey(keyBytes); } - - async rsaDecrypt(data: EncString, privateKey: Uint8Array): Promise { - if (data == null) { - throw new Error("[Encrypt service] rsaDecrypt: No data provided for decryption."); - } - - switch (data.encryptionType) { - case EncryptionType.Rsa2048_OaepSha1_B64: - case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: - break; - default: - throw new Error("Invalid encryption type."); - } - - if (privateKey == null) { - throw new Error("[Encrypt service] rsaDecrypt: No private key provided for decryption."); - } - - return this.cryptoFunctionService.rsaDecrypt(data.dataBytes, privateKey, "sha1"); - } }