mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
[PM-5499] Create Auth Request Service (#8056)
* create auth request service * copy methods from auth crypto service * register new auth request service * remove refs to auth request crypto service * remove auth request crypto service * remove passwordless login method from login strategy service * add docs to auth request service
This commit is contained in:
@@ -1,29 +0,0 @@
|
|||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthRequestCryptoServiceImplementation } from "@bitwarden/common/auth/services/auth-request-crypto.service.implementation";
|
|
||||||
|
|
||||||
import {
|
|
||||||
CryptoServiceInitOptions,
|
|
||||||
cryptoServiceFactory,
|
|
||||||
} from "../../../platform/background/service-factories/crypto-service.factory";
|
|
||||||
import {
|
|
||||||
CachedServices,
|
|
||||||
FactoryOptions,
|
|
||||||
factory,
|
|
||||||
} from "../../../platform/background/service-factories/factory-options";
|
|
||||||
|
|
||||||
type AuthRequestCryptoServiceFactoryOptions = FactoryOptions;
|
|
||||||
|
|
||||||
export type AuthRequestCryptoServiceInitOptions = AuthRequestCryptoServiceFactoryOptions &
|
|
||||||
CryptoServiceInitOptions;
|
|
||||||
|
|
||||||
export function authRequestCryptoServiceFactory(
|
|
||||||
cache: { authRequestCryptoService?: AuthRequestCryptoServiceAbstraction } & CachedServices,
|
|
||||||
opts: AuthRequestCryptoServiceInitOptions,
|
|
||||||
): Promise<AuthRequestCryptoServiceAbstraction> {
|
|
||||||
return factory(
|
|
||||||
cache,
|
|
||||||
"authRequestCryptoService",
|
|
||||||
opts,
|
|
||||||
async () => new AuthRequestCryptoServiceImplementation(await cryptoServiceFactory(cache, opts)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { AuthRequestService, AuthRequestServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
|
|
||||||
|
import {
|
||||||
|
apiServiceFactory,
|
||||||
|
ApiServiceInitOptions,
|
||||||
|
} from "../../../platform/background/service-factories/api-service.factory";
|
||||||
|
import {
|
||||||
|
appIdServiceFactory,
|
||||||
|
AppIdServiceInitOptions,
|
||||||
|
} from "../../../platform/background/service-factories/app-id-service.factory";
|
||||||
|
import {
|
||||||
|
CryptoServiceInitOptions,
|
||||||
|
cryptoServiceFactory,
|
||||||
|
} from "../../../platform/background/service-factories/crypto-service.factory";
|
||||||
|
import {
|
||||||
|
CachedServices,
|
||||||
|
FactoryOptions,
|
||||||
|
factory,
|
||||||
|
} from "../../../platform/background/service-factories/factory-options";
|
||||||
|
import {
|
||||||
|
stateServiceFactory,
|
||||||
|
StateServiceInitOptions,
|
||||||
|
} from "../../../platform/background/service-factories/state-service.factory";
|
||||||
|
|
||||||
|
type AuthRequestServiceFactoryOptions = FactoryOptions;
|
||||||
|
|
||||||
|
export type AuthRequestServiceInitOptions = AuthRequestServiceFactoryOptions &
|
||||||
|
AppIdServiceInitOptions &
|
||||||
|
CryptoServiceInitOptions &
|
||||||
|
ApiServiceInitOptions &
|
||||||
|
StateServiceInitOptions;
|
||||||
|
|
||||||
|
export function authRequestServiceFactory(
|
||||||
|
cache: { authRequestService?: AuthRequestServiceAbstraction } & CachedServices,
|
||||||
|
opts: AuthRequestServiceInitOptions,
|
||||||
|
): Promise<AuthRequestServiceAbstraction> {
|
||||||
|
return factory(
|
||||||
|
cache,
|
||||||
|
"authRequestService",
|
||||||
|
opts,
|
||||||
|
async () =>
|
||||||
|
new AuthRequestService(
|
||||||
|
await appIdServiceFactory(cache, opts),
|
||||||
|
await cryptoServiceFactory(cache, opts),
|
||||||
|
await apiServiceFactory(cache, opts),
|
||||||
|
await stateServiceFactory(cache, opts),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -52,9 +52,9 @@ import {
|
|||||||
} from "../../../tools/background/service_factories/password-strength-service.factory";
|
} from "../../../tools/background/service_factories/password-strength-service.factory";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
authRequestCryptoServiceFactory,
|
authRequestServiceFactory,
|
||||||
AuthRequestCryptoServiceInitOptions,
|
AuthRequestServiceInitOptions,
|
||||||
} from "./auth-request-crypto-service.factory";
|
} from "./auth-request-service.factory";
|
||||||
import {
|
import {
|
||||||
deviceTrustCryptoServiceFactory,
|
deviceTrustCryptoServiceFactory,
|
||||||
DeviceTrustCryptoServiceInitOptions,
|
DeviceTrustCryptoServiceInitOptions,
|
||||||
@@ -84,7 +84,7 @@ export type LoginStrategyServiceInitOptions = LoginStrategyServiceFactoryOptions
|
|||||||
PolicyServiceInitOptions &
|
PolicyServiceInitOptions &
|
||||||
PasswordStrengthServiceInitOptions &
|
PasswordStrengthServiceInitOptions &
|
||||||
DeviceTrustCryptoServiceInitOptions &
|
DeviceTrustCryptoServiceInitOptions &
|
||||||
AuthRequestCryptoServiceInitOptions;
|
AuthRequestServiceInitOptions;
|
||||||
|
|
||||||
export function loginStrategyServiceFactory(
|
export function loginStrategyServiceFactory(
|
||||||
cache: { loginStrategyService?: LoginStrategyServiceAbstraction } & CachedServices,
|
cache: { loginStrategyService?: LoginStrategyServiceAbstraction } & CachedServices,
|
||||||
@@ -112,7 +112,7 @@ export function loginStrategyServiceFactory(
|
|||||||
await passwordStrengthServiceFactory(cache, opts),
|
await passwordStrengthServiceFactory(cache, opts),
|
||||||
await policyServiceFactory(cache, opts),
|
await policyServiceFactory(cache, opts),
|
||||||
await deviceTrustCryptoServiceFactory(cache, opts),
|
await deviceTrustCryptoServiceFactory(cache, opts),
|
||||||
await authRequestCryptoServiceFactory(cache, opts),
|
await authRequestServiceFactory(cache, opts),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
|
|||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component";
|
import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
@@ -48,7 +50,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
loginService: LoginService,
|
loginService: LoginService,
|
||||||
syncService: SyncService,
|
syncService: SyncService,
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
authRequestService: AuthRequestServiceAbstraction,
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction,
|
loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
private location: Location,
|
private location: Location,
|
||||||
) {
|
) {
|
||||||
@@ -69,7 +71,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
stateService,
|
stateService,
|
||||||
loginService,
|
loginService,
|
||||||
deviceTrustCryptoService,
|
deviceTrustCryptoService,
|
||||||
authReqCryptoService,
|
authRequestService,
|
||||||
loginStrategyService,
|
loginStrategyService,
|
||||||
);
|
);
|
||||||
super.onSuccessfulLogin = async () => {
|
super.onSuccessfulLogin = async () => {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import {
|
|||||||
PinCryptoService,
|
PinCryptoService,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
LoginStrategyService,
|
LoginStrategyService,
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
|
AuthRequestService,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { AvatarUpdateService as AvatarUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
import { AvatarUpdateService as AvatarUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service";
|
||||||
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
||||||
@@ -22,7 +24,6 @@ import { ProviderService as ProviderServiceAbstraction } from "@bitwarden/common
|
|||||||
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
||||||
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
||||||
@@ -35,7 +36,6 @@ import { UserVerificationService as UserVerificationServiceAbstraction } from "@
|
|||||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||||
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AuthRequestCryptoServiceImplementation } from "@bitwarden/common/auth/services/auth-request-crypto.service.implementation";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
||||||
@@ -274,7 +274,7 @@ export default class MainBackground {
|
|||||||
devicesApiService: DevicesApiServiceAbstraction;
|
devicesApiService: DevicesApiServiceAbstraction;
|
||||||
devicesService: DevicesServiceAbstraction;
|
devicesService: DevicesServiceAbstraction;
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction;
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction;
|
||||||
authRequestCryptoService: AuthRequestCryptoServiceAbstraction;
|
authRequestService: AuthRequestServiceAbstraction;
|
||||||
accountService: AccountServiceAbstraction;
|
accountService: AccountServiceAbstraction;
|
||||||
globalStateProvider: GlobalStateProvider;
|
globalStateProvider: GlobalStateProvider;
|
||||||
pinCryptoService: PinCryptoServiceAbstraction;
|
pinCryptoService: PinCryptoServiceAbstraction;
|
||||||
@@ -531,7 +531,12 @@ export default class MainBackground {
|
|||||||
|
|
||||||
this.devicesService = new DevicesServiceImplementation(this.devicesApiService);
|
this.devicesService = new DevicesServiceImplementation(this.devicesApiService);
|
||||||
|
|
||||||
this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService);
|
this.authRequestService = new AuthRequestService(
|
||||||
|
this.appIdService,
|
||||||
|
this.cryptoService,
|
||||||
|
this.apiService,
|
||||||
|
this.stateService,
|
||||||
|
);
|
||||||
|
|
||||||
this.authService = new AuthService(
|
this.authService = new AuthService(
|
||||||
backgroundMessagingService,
|
backgroundMessagingService,
|
||||||
@@ -557,7 +562,7 @@ export default class MainBackground {
|
|||||||
this.passwordStrengthService,
|
this.passwordStrengthService,
|
||||||
this.policyService,
|
this.policyService,
|
||||||
this.deviceTrustCryptoService,
|
this.deviceTrustCryptoService,
|
||||||
this.authRequestCryptoService,
|
this.authRequestService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
|
this.userVerificationApiService = new UserVerificationApiService(this.apiService);
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ import {
|
|||||||
OBSERVABLE_MEMORY_STORAGE,
|
OBSERVABLE_MEMORY_STORAGE,
|
||||||
} from "@bitwarden/angular/services/injection-tokens";
|
} from "@bitwarden/angular/services/injection-tokens";
|
||||||
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
import { JslibServicesModule } from "@bitwarden/angular/services/jslib-services.module";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
@@ -29,7 +32,6 @@ import {
|
|||||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||||
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
import { PolicyApiService } from "@bitwarden/common/admin-console/services/policy/policy-api.service";
|
||||||
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
||||||
@@ -296,8 +298,8 @@ function getBgService<T>(service: keyof MainBackground) {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: AuthRequestCryptoServiceAbstraction,
|
provide: AuthRequestServiceAbstraction,
|
||||||
useFactory: getBgService<AuthRequestCryptoServiceAbstraction>("authRequestCryptoService"),
|
useFactory: getBgService<AuthRequestServiceAbstraction>("authRequestService"),
|
||||||
deps: [],
|
deps: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { program } from "commander";
|
|||||||
import * as jsdom from "jsdom";
|
import * as jsdom from "jsdom";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
AuthRequestService,
|
||||||
LoginStrategyService,
|
LoginStrategyService,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
PinCryptoService,
|
PinCryptoService,
|
||||||
@@ -22,11 +23,9 @@ import { PolicyApiService } from "@bitwarden/common/admin-console/services/polic
|
|||||||
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
import { PolicyService } from "@bitwarden/common/admin-console/services/policy/policy.service";
|
||||||
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
import { ProviderService } from "@bitwarden/common/admin-console/services/provider.service";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AuthRequestCryptoServiceImplementation } from "@bitwarden/common/auth/services/auth-request-crypto.service.implementation";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
import { DevicesApiServiceImplementation } from "@bitwarden/common/auth/services/devices-api.service.implementation";
|
||||||
@@ -196,7 +195,7 @@ export class Main {
|
|||||||
sendApiService: SendApiService;
|
sendApiService: SendApiService;
|
||||||
devicesApiService: DevicesApiServiceAbstraction;
|
devicesApiService: DevicesApiServiceAbstraction;
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction;
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction;
|
||||||
authRequestCryptoService: AuthRequestCryptoServiceAbstraction;
|
authRequestService: AuthRequestService;
|
||||||
configApiService: ConfigApiServiceAbstraction;
|
configApiService: ConfigApiServiceAbstraction;
|
||||||
configService: CliConfigService;
|
configService: CliConfigService;
|
||||||
accountService: AccountService;
|
accountService: AccountService;
|
||||||
@@ -418,7 +417,12 @@ export class Main {
|
|||||||
this.platformUtilsService,
|
this.platformUtilsService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService);
|
this.authRequestService = new AuthRequestService(
|
||||||
|
this.appIdService,
|
||||||
|
this.cryptoService,
|
||||||
|
this.apiService,
|
||||||
|
this.stateService,
|
||||||
|
);
|
||||||
|
|
||||||
this.loginStrategyService = new LoginStrategyService(
|
this.loginStrategyService = new LoginStrategyService(
|
||||||
this.cryptoService,
|
this.cryptoService,
|
||||||
@@ -437,7 +441,7 @@ export class Main {
|
|||||||
this.passwordStrengthService,
|
this.passwordStrengthService,
|
||||||
this.policyService,
|
this.policyService,
|
||||||
this.deviceTrustCryptoService,
|
this.deviceTrustCryptoService,
|
||||||
this.authRequestCryptoService,
|
this.authRequestService,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.authService = new AuthService(
|
this.authService = new AuthService(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Component, OnInit, OnDestroy, Inject } from "@angular/core";
|
|||||||
import { Subject, firstValueFrom } from "rxjs";
|
import { Subject, firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import { AuthRequestServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
@@ -46,11 +46,11 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) private params: LoginApprovalDialogParams,
|
@Inject(DIALOG_DATA) private params: LoginApprovalDialogParams,
|
||||||
|
protected authRequestService: AuthRequestServiceAbstraction,
|
||||||
protected stateService: StateService,
|
protected stateService: StateService,
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected apiService: ApiService,
|
protected apiService: ApiService,
|
||||||
protected loginStrategyService: LoginStrategyServiceAbstraction,
|
|
||||||
protected appIdService: AppIdService,
|
protected appIdService: AppIdService,
|
||||||
protected cryptoService: CryptoService,
|
protected cryptoService: CryptoService,
|
||||||
private dialogRef: DialogRef,
|
private dialogRef: DialogRef,
|
||||||
@@ -121,10 +121,9 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
|
|||||||
this.i18nService.t("thisRequestIsNoLongerValid"),
|
this.i18nService.t("thisRequestIsNoLongerValid"),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const loginResponse = await this.loginStrategyService.passwordlessLogin(
|
const loginResponse = await this.authRequestService.approveOrDenyAuthRequest(
|
||||||
this.authRequestResponse.id,
|
|
||||||
this.authRequestResponse.publicKey,
|
|
||||||
approve,
|
approve,
|
||||||
|
this.authRequestResponse,
|
||||||
);
|
);
|
||||||
this.showResultToast(loginResponse);
|
this.showResultToast(loginResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import { Router } from "@angular/router";
|
|||||||
|
|
||||||
import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component";
|
import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
@@ -56,7 +58,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
loginService: LoginService,
|
loginService: LoginService,
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
authRequestService: AuthRequestServiceAbstraction,
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction,
|
loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
private location: Location,
|
private location: Location,
|
||||||
) {
|
) {
|
||||||
@@ -77,7 +79,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
stateService,
|
stateService,
|
||||||
loginService,
|
loginService,
|
||||||
deviceTrustCryptoService,
|
deviceTrustCryptoService,
|
||||||
authReqCryptoService,
|
authRequestService,
|
||||||
loginStrategyService,
|
loginStrategyService,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
|
|||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component";
|
import { LoginViaAuthRequestComponent as BaseLoginWithDeviceComponent } from "@bitwarden/angular/auth/components/login-via-auth-request.component";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import {
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
|
LoginStrategyServiceAbstraction,
|
||||||
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
@@ -46,7 +48,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
stateService: StateService,
|
stateService: StateService,
|
||||||
loginService: LoginService,
|
loginService: LoginService,
|
||||||
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
authRequestService: AuthRequestServiceAbstraction,
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction,
|
loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
@@ -66,7 +68,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
stateService,
|
stateService,
|
||||||
loginService,
|
loginService,
|
||||||
deviceTrustCryptoService,
|
deviceTrustCryptoService,
|
||||||
authReqCryptoService,
|
authRequestService,
|
||||||
loginStrategyService,
|
loginStrategyService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import { Subject, takeUntil } from "rxjs";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
AuthRequestLoginCredentials,
|
AuthRequestLoginCredentials,
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
|
||||||
@@ -86,7 +86,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private loginService: LoginService,
|
private loginService: LoginService,
|
||||||
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
private authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
private authRequestService: AuthRequestServiceAbstraction,
|
||||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
) {
|
) {
|
||||||
super(environmentService, i18nService, platformUtilsService);
|
super(environmentService, i18nService, platformUtilsService);
|
||||||
@@ -367,14 +367,14 @@ export class LoginViaAuthRequestComponent
|
|||||||
if (adminAuthReqResponse.masterPasswordHash) {
|
if (adminAuthReqResponse.masterPasswordHash) {
|
||||||
// Flow 2: masterPasswordHash is not null
|
// Flow 2: masterPasswordHash is not null
|
||||||
// key is authRequestPublicKey(masterKey) + we have authRequestPublicKey(masterPasswordHash)
|
// key is authRequestPublicKey(masterKey) + we have authRequestPublicKey(masterPasswordHash)
|
||||||
await this.authReqCryptoService.setKeysAfterDecryptingSharedMasterKeyAndHash(
|
await this.authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash(
|
||||||
adminAuthReqResponse,
|
adminAuthReqResponse,
|
||||||
privateKey,
|
privateKey,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Flow 3: masterPasswordHash is null
|
// Flow 3: masterPasswordHash is null
|
||||||
// we can assume key is authRequestPublicKey(userKey) and we can just decrypt with userKey and proceed to vault
|
// we can assume key is authRequestPublicKey(userKey) and we can just decrypt with userKey and proceed to vault
|
||||||
await this.authReqCryptoService.setUserKeyAfterDecryptingSharedUserKey(
|
await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey(
|
||||||
adminAuthReqResponse,
|
adminAuthReqResponse,
|
||||||
privateKey,
|
privateKey,
|
||||||
);
|
);
|
||||||
@@ -404,7 +404,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
// if masterPasswordHash is null, we will always receive key as authRequestPublicKey(userKey)
|
// if masterPasswordHash is null, we will always receive key as authRequestPublicKey(userKey)
|
||||||
if (response.masterPasswordHash) {
|
if (response.masterPasswordHash) {
|
||||||
const { masterKey, masterKeyHash } =
|
const { masterKey, masterKeyHash } =
|
||||||
await this.authReqCryptoService.decryptPubKeyEncryptedMasterKeyAndHash(
|
await this.authRequestService.decryptPubKeyEncryptedMasterKeyAndHash(
|
||||||
response.key,
|
response.key,
|
||||||
response.masterPasswordHash,
|
response.masterPasswordHash,
|
||||||
this.authRequestKeyPair.privateKey,
|
this.authRequestKeyPair.privateKey,
|
||||||
@@ -419,7 +419,7 @@ export class LoginViaAuthRequestComponent
|
|||||||
masterKeyHash,
|
masterKeyHash,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const userKey = await this.authReqCryptoService.decryptPubKeyEncryptedUserKey(
|
const userKey = await this.authRequestService.decryptPubKeyEncryptedUserKey(
|
||||||
response.key,
|
response.key,
|
||||||
this.authRequestKeyPair.privateKey,
|
this.authRequestKeyPair.privateKey,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { LOCALE_ID, NgModule } from "@angular/core";
|
import { LOCALE_ID, NgModule } from "@angular/core";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
AuthRequestServiceAbstraction,
|
||||||
|
AuthRequestService,
|
||||||
PinCryptoServiceAbstraction,
|
PinCryptoServiceAbstraction,
|
||||||
PinCryptoService,
|
PinCryptoService,
|
||||||
LoginStrategyServiceAbstraction,
|
LoginStrategyServiceAbstraction,
|
||||||
@@ -47,7 +49,6 @@ import {
|
|||||||
InternalAccountService,
|
InternalAccountService,
|
||||||
} from "@bitwarden/common/auth/abstractions/account.service";
|
} from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { AnonymousHubService as AnonymousHubServiceAbstraction } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
import { AnonymousHubService as AnonymousHubServiceAbstraction } from "@bitwarden/common/auth/abstractions/anonymous-hub.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
import { AuthService as AuthServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth.service";
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
import { DevicesServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices/devices.service.abstraction";
|
||||||
@@ -66,7 +67,6 @@ import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstract
|
|||||||
import { AccountApiServiceImplementation } from "@bitwarden/common/auth/services/account-api.service";
|
import { AccountApiServiceImplementation } from "@bitwarden/common/auth/services/account-api.service";
|
||||||
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
import { AccountServiceImplementation } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { AnonymousHubService } from "@bitwarden/common/auth/services/anonymous-hub.service";
|
import { AnonymousHubService } from "@bitwarden/common/auth/services/anonymous-hub.service";
|
||||||
import { AuthRequestCryptoServiceImplementation } from "@bitwarden/common/auth/services/auth-request-crypto.service.implementation";
|
|
||||||
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
import { AuthService } from "@bitwarden/common/auth/services/auth.service";
|
||||||
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
import { DeviceTrustCryptoService } from "@bitwarden/common/auth/services/device-trust-crypto.service.implementation";
|
||||||
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
import { DevicesServiceImplementation } from "@bitwarden/common/auth/services/devices/devices.service.implementation";
|
||||||
@@ -320,7 +320,7 @@ import { ModalService } from "./modal.service";
|
|||||||
PasswordStrengthServiceAbstraction,
|
PasswordStrengthServiceAbstraction,
|
||||||
PolicyServiceAbstraction,
|
PolicyServiceAbstraction,
|
||||||
DeviceTrustCryptoServiceAbstraction,
|
DeviceTrustCryptoServiceAbstraction,
|
||||||
AuthRequestCryptoServiceAbstraction,
|
AuthRequestServiceAbstraction,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -845,9 +845,14 @@ import { ModalService } from "./modal.service";
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: AuthRequestCryptoServiceAbstraction,
|
provide: AuthRequestServiceAbstraction,
|
||||||
useClass: AuthRequestCryptoServiceImplementation,
|
useClass: AuthRequestService,
|
||||||
deps: [CryptoServiceAbstraction],
|
deps: [
|
||||||
|
AppIdServiceAbstraction,
|
||||||
|
CryptoServiceAbstraction,
|
||||||
|
ApiServiceAbstraction,
|
||||||
|
StateServiceAbstraction,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: PinCryptoServiceAbstraction,
|
provide: PinCryptoServiceAbstraction,
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||||
|
import { UserKey, MasterKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
|
export abstract class AuthRequestServiceAbstraction {
|
||||||
|
/**
|
||||||
|
* Approve or deny an auth request.
|
||||||
|
* @param approve True to approve, false to deny.
|
||||||
|
* @param authRequest The auth request to approve or deny, must have an id and key.
|
||||||
|
* @returns The updated auth request, the `requestApproved` field will be true if
|
||||||
|
* approval was successful.
|
||||||
|
* @throws If the auth request is missing an id or key.
|
||||||
|
*/
|
||||||
|
abstract approveOrDenyAuthRequest: (
|
||||||
|
approve: boolean,
|
||||||
|
authRequest: AuthRequestResponse,
|
||||||
|
) => Promise<AuthRequestResponse>;
|
||||||
|
/**
|
||||||
|
* Sets the `UserKey` from an auth request. Auth request must have a `UserKey`.
|
||||||
|
* @param authReqResponse The auth request.
|
||||||
|
* @param authReqPrivateKey The private key corresponding to the public key sent in the auth request.
|
||||||
|
*/
|
||||||
|
abstract setUserKeyAfterDecryptingSharedUserKey: (
|
||||||
|
authReqResponse: AuthRequestResponse,
|
||||||
|
authReqPrivateKey: ArrayBuffer,
|
||||||
|
) => Promise<void>;
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
abstract setKeysAfterDecryptingSharedMasterKeyAndHash: (
|
||||||
|
authReqResponse: AuthRequestResponse,
|
||||||
|
authReqPrivateKey: ArrayBuffer,
|
||||||
|
) => Promise<void>;
|
||||||
|
/**
|
||||||
|
* Decrypts a `UserKey` from a public key encrypted `UserKey`.
|
||||||
|
* @param pubKeyEncryptedUserKey The public key encrypted `UserKey`.
|
||||||
|
* @param privateKey The private key corresponding to the public key used to encrypt the `UserKey`.
|
||||||
|
* @returns The decrypted `UserKey`.
|
||||||
|
*/
|
||||||
|
abstract decryptPubKeyEncryptedUserKey: (
|
||||||
|
pubKeyEncryptedUserKey: string,
|
||||||
|
privateKey: ArrayBuffer,
|
||||||
|
) => Promise<UserKey>;
|
||||||
|
/**
|
||||||
|
* 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: ArrayBuffer,
|
||||||
|
) => Promise<{ masterKey: MasterKey; masterKeyHash: string }>;
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from "./pin-crypto.service.abstraction";
|
export * from "./pin-crypto.service.abstraction";
|
||||||
export * from "./login-strategy.service";
|
export * from "./login-strategy.service";
|
||||||
|
export * from "./auth-request.service.abstraction";
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Observable } from "rxjs";
|
|||||||
|
|
||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
||||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
|
||||||
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
|
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
|
||||||
import { MasterKey } from "@bitwarden/common/types/key";
|
import { MasterKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
@@ -39,10 +38,5 @@ export abstract class LoginStrategyServiceAbstraction {
|
|||||||
authingWithPassword: () => boolean;
|
authingWithPassword: () => boolean;
|
||||||
authingWithPasswordless: () => boolean;
|
authingWithPasswordless: () => boolean;
|
||||||
authResponsePushNotification: (notification: AuthRequestPushNotification) => Promise<any>;
|
authResponsePushNotification: (notification: AuthRequestPushNotification) => Promise<any>;
|
||||||
passwordlessLogin: (
|
|
||||||
id: string,
|
|
||||||
key: string,
|
|
||||||
requestApproved: boolean,
|
|
||||||
) => Promise<AuthRequestResponse>;
|
|
||||||
getPushNotificationObs$: () => Observable<any>;
|
getPushNotificationObs$: () => Observable<any>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { mock, MockProxy } from "jest-mock-extended";
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
@@ -20,6 +19,7 @@ import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/sym
|
|||||||
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
import { CsprngArray } from "@bitwarden/common/types/csprng";
|
||||||
import { DeviceKey, UserKey, MasterKey } from "@bitwarden/common/types/key";
|
import { DeviceKey, UserKey, MasterKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
|
import { AuthRequestServiceAbstraction } from "../abstractions";
|
||||||
import { SsoLoginCredentials } from "../models/domain/login-credentials";
|
import { SsoLoginCredentials } from "../models/domain/login-credentials";
|
||||||
|
|
||||||
import { identityTokenResponseFactory } from "./login.strategy.spec";
|
import { identityTokenResponseFactory } from "./login.strategy.spec";
|
||||||
@@ -40,7 +40,7 @@ describe("SsoLoginStrategy", () => {
|
|||||||
let twoFactorService: MockProxy<TwoFactorService>;
|
let twoFactorService: MockProxy<TwoFactorService>;
|
||||||
let keyConnectorService: MockProxy<KeyConnectorService>;
|
let keyConnectorService: MockProxy<KeyConnectorService>;
|
||||||
let deviceTrustCryptoService: MockProxy<DeviceTrustCryptoServiceAbstraction>;
|
let deviceTrustCryptoService: MockProxy<DeviceTrustCryptoServiceAbstraction>;
|
||||||
let authRequestCryptoService: MockProxy<AuthRequestCryptoServiceAbstraction>;
|
let authRequestService: MockProxy<AuthRequestServiceAbstraction>;
|
||||||
let i18nService: MockProxy<I18nService>;
|
let i18nService: MockProxy<I18nService>;
|
||||||
|
|
||||||
let ssoLoginStrategy: SsoLoginStrategy;
|
let ssoLoginStrategy: SsoLoginStrategy;
|
||||||
@@ -66,7 +66,7 @@ describe("SsoLoginStrategy", () => {
|
|||||||
twoFactorService = mock<TwoFactorService>();
|
twoFactorService = mock<TwoFactorService>();
|
||||||
keyConnectorService = mock<KeyConnectorService>();
|
keyConnectorService = mock<KeyConnectorService>();
|
||||||
deviceTrustCryptoService = mock<DeviceTrustCryptoServiceAbstraction>();
|
deviceTrustCryptoService = mock<DeviceTrustCryptoServiceAbstraction>();
|
||||||
authRequestCryptoService = mock<AuthRequestCryptoServiceAbstraction>();
|
authRequestService = mock<AuthRequestServiceAbstraction>();
|
||||||
i18nService = mock<I18nService>();
|
i18nService = mock<I18nService>();
|
||||||
|
|
||||||
tokenService.getTwoFactorToken.mockResolvedValue(null);
|
tokenService.getTwoFactorToken.mockResolvedValue(null);
|
||||||
@@ -85,7 +85,7 @@ describe("SsoLoginStrategy", () => {
|
|||||||
twoFactorService,
|
twoFactorService,
|
||||||
keyConnectorService,
|
keyConnectorService,
|
||||||
deviceTrustCryptoService,
|
deviceTrustCryptoService,
|
||||||
authRequestCryptoService,
|
authRequestService,
|
||||||
i18nService,
|
i18nService,
|
||||||
);
|
);
|
||||||
credentials = new SsoLoginCredentials(ssoCode, ssoCodeVerifier, ssoRedirectUrl, ssoOrgId);
|
credentials = new SsoLoginCredentials(ssoCode, ssoCodeVerifier, ssoRedirectUrl, ssoOrgId);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
@@ -18,6 +17,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
|
|
||||||
|
import { AuthRequestServiceAbstraction } from "../abstractions";
|
||||||
import { SsoLoginCredentials } from "../models/domain/login-credentials";
|
import { SsoLoginCredentials } from "../models/domain/login-credentials";
|
||||||
|
|
||||||
import { LoginStrategy } from "./login.strategy";
|
import { LoginStrategy } from "./login.strategy";
|
||||||
@@ -44,7 +44,7 @@ export class SsoLoginStrategy extends LoginStrategy {
|
|||||||
twoFactorService: TwoFactorService,
|
twoFactorService: TwoFactorService,
|
||||||
private keyConnectorService: KeyConnectorService,
|
private keyConnectorService: KeyConnectorService,
|
||||||
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
private authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
private authRequestService: AuthRequestServiceAbstraction,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
@@ -199,14 +199,14 @@ export class SsoLoginStrategy extends LoginStrategy {
|
|||||||
// if masterPasswordHash has a value, we will always receive authReqResponse.key
|
// if masterPasswordHash has a value, we will always receive authReqResponse.key
|
||||||
// as authRequestPublicKey(masterKey) + authRequestPublicKey(masterPasswordHash)
|
// as authRequestPublicKey(masterKey) + authRequestPublicKey(masterPasswordHash)
|
||||||
if (adminAuthReqResponse.masterPasswordHash) {
|
if (adminAuthReqResponse.masterPasswordHash) {
|
||||||
await this.authReqCryptoService.setKeysAfterDecryptingSharedMasterKeyAndHash(
|
await this.authRequestService.setKeysAfterDecryptingSharedMasterKeyAndHash(
|
||||||
adminAuthReqResponse,
|
adminAuthReqResponse,
|
||||||
adminAuthReqStorable.privateKey,
|
adminAuthReqStorable.privateKey,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// if masterPasswordHash is null, we will always receive authReqResponse.key
|
// if masterPasswordHash is null, we will always receive authReqResponse.key
|
||||||
// as authRequestPublicKey(userKey)
|
// as authRequestPublicKey(userKey)
|
||||||
await this.authReqCryptoService.setUserKeyAfterDecryptingSharedUserKey(
|
await this.authRequestService.setUserKeyAfterDecryptingSharedUserKey(
|
||||||
adminAuthReqResponse,
|
adminAuthReqResponse,
|
||||||
adminAuthReqStorable.privateKey,
|
adminAuthReqStorable.privateKey,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,32 +1,71 @@
|
|||||||
import { mock } from "jest-mock-extended";
|
import { mock } from "jest-mock-extended";
|
||||||
|
|
||||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { Utils } from "../../platform/misc/utils";
|
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||||
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { UserKey, MasterKey } from "../../types/key";
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "../abstractions/auth-request-crypto.service.abstraction";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { AuthRequestResponse } from "../models/response/auth-request.response";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
|
||||||
|
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
|
import { MasterKey, UserKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
import { AuthRequestCryptoServiceImplementation } from "./auth-request-crypto.service.implementation";
|
import { AuthRequestService } from "./auth-request.service";
|
||||||
|
|
||||||
describe("AuthRequestCryptoService", () => {
|
describe("AuthRequestService", () => {
|
||||||
let authReqCryptoService: AuthRequestCryptoServiceAbstraction;
|
let sut: AuthRequestService;
|
||||||
|
|
||||||
|
const appIdService = mock<AppIdService>();
|
||||||
const cryptoService = mock<CryptoService>();
|
const cryptoService = mock<CryptoService>();
|
||||||
|
const apiService = mock<ApiService>();
|
||||||
|
const stateService = mock<StateService>();
|
||||||
|
|
||||||
let mockPrivateKey: Uint8Array;
|
let mockPrivateKey: Uint8Array;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
jest.resetAllMocks();
|
|
||||||
|
|
||||||
authReqCryptoService = new AuthRequestCryptoServiceImplementation(cryptoService);
|
sut = new AuthRequestService(appIdService, cryptoService, apiService, stateService);
|
||||||
|
|
||||||
mockPrivateKey = new Uint8Array(64);
|
mockPrivateKey = new Uint8Array(64);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("instantiates", () => {
|
describe("approveOrDenyAuthRequest", () => {
|
||||||
expect(authReqCryptoService).not.toBeFalsy();
|
beforeEach(() => {
|
||||||
|
cryptoService.rsaEncrypt.mockResolvedValue({
|
||||||
|
encryptedString: "ENCRYPTED_STRING",
|
||||||
|
} as EncString);
|
||||||
|
appIdService.getAppId.mockResolvedValue("APP_ID");
|
||||||
|
});
|
||||||
|
it("should throw if auth request is missing id or key", async () => {
|
||||||
|
const authRequestNoId = new AuthRequestResponse({ id: "", key: "KEY" });
|
||||||
|
const authRequestNoKey = new AuthRequestResponse({ id: "123", key: "" });
|
||||||
|
|
||||||
|
await expect(sut.approveOrDenyAuthRequest(true, authRequestNoId)).rejects.toThrow(
|
||||||
|
"Auth request has no id",
|
||||||
|
);
|
||||||
|
await expect(sut.approveOrDenyAuthRequest(true, authRequestNoKey)).rejects.toThrow(
|
||||||
|
"Auth request has no public key",
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should use the master key and hash if they exist", async () => {
|
||||||
|
cryptoService.getMasterKey.mockResolvedValueOnce({ encKey: new Uint8Array(64) } as MasterKey);
|
||||||
|
stateService.getKeyHash.mockResolvedValueOnce("KEY_HASH");
|
||||||
|
|
||||||
|
await sut.approveOrDenyAuthRequest(true, new AuthRequestResponse({ id: "123", key: "KEY" }));
|
||||||
|
|
||||||
|
expect(cryptoService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should use the user key if the master key and hash do not exist", async () => {
|
||||||
|
cryptoService.getUserKey.mockResolvedValueOnce({ key: new Uint8Array(64) } as UserKey);
|
||||||
|
|
||||||
|
await sut.approveOrDenyAuthRequest(true, new AuthRequestResponse({ id: "123", key: "KEY" }));
|
||||||
|
|
||||||
|
expect(cryptoService.rsaEncrypt).toHaveBeenCalledWith(new Uint8Array(64), expect.anything());
|
||||||
|
});
|
||||||
|
});
|
||||||
describe("setUserKeyAfterDecryptingSharedUserKey", () => {
|
describe("setUserKeyAfterDecryptingSharedUserKey", () => {
|
||||||
it("decrypts and sets user key when given valid auth request response and private key", async () => {
|
it("decrypts and sets user key when given valid auth request response and private key", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
@@ -35,20 +74,15 @@ describe("AuthRequestCryptoService", () => {
|
|||||||
} as AuthRequestResponse;
|
} as AuthRequestResponse;
|
||||||
|
|
||||||
const mockDecryptedUserKey = {} as UserKey;
|
const mockDecryptedUserKey = {} as UserKey;
|
||||||
jest
|
jest.spyOn(sut, "decryptPubKeyEncryptedUserKey").mockResolvedValueOnce(mockDecryptedUserKey);
|
||||||
.spyOn(authReqCryptoService, "decryptPubKeyEncryptedUserKey")
|
|
||||||
.mockResolvedValueOnce(mockDecryptedUserKey);
|
|
||||||
|
|
||||||
cryptoService.setUserKey.mockResolvedValueOnce(undefined);
|
cryptoService.setUserKey.mockResolvedValueOnce(undefined);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authReqCryptoService.setUserKeyAfterDecryptingSharedUserKey(
|
await sut.setUserKeyAfterDecryptingSharedUserKey(mockAuthReqResponse, mockPrivateKey);
|
||||||
mockAuthReqResponse,
|
|
||||||
mockPrivateKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(authReqCryptoService.decryptPubKeyEncryptedUserKey).toBeCalledWith(
|
expect(sut.decryptPubKeyEncryptedUserKey).toBeCalledWith(
|
||||||
mockAuthReqResponse.key,
|
mockAuthReqResponse.key,
|
||||||
mockPrivateKey,
|
mockPrivateKey,
|
||||||
);
|
);
|
||||||
@@ -68,9 +102,7 @@ describe("AuthRequestCryptoService", () => {
|
|||||||
const mockDecryptedMasterKeyHash = "mockDecryptedMasterKeyHash";
|
const mockDecryptedMasterKeyHash = "mockDecryptedMasterKeyHash";
|
||||||
const mockDecryptedUserKey = {} as UserKey;
|
const mockDecryptedUserKey = {} as UserKey;
|
||||||
|
|
||||||
jest
|
jest.spyOn(sut, "decryptPubKeyEncryptedMasterKeyAndHash").mockResolvedValueOnce({
|
||||||
.spyOn(authReqCryptoService, "decryptPubKeyEncryptedMasterKeyAndHash")
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
masterKey: mockDecryptedMasterKey,
|
masterKey: mockDecryptedMasterKey,
|
||||||
masterKeyHash: mockDecryptedMasterKeyHash,
|
masterKeyHash: mockDecryptedMasterKeyHash,
|
||||||
});
|
});
|
||||||
@@ -81,13 +113,10 @@ describe("AuthRequestCryptoService", () => {
|
|||||||
cryptoService.setUserKey.mockResolvedValueOnce(undefined);
|
cryptoService.setUserKey.mockResolvedValueOnce(undefined);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await authReqCryptoService.setKeysAfterDecryptingSharedMasterKeyAndHash(
|
await sut.setKeysAfterDecryptingSharedMasterKeyAndHash(mockAuthReqResponse, mockPrivateKey);
|
||||||
mockAuthReqResponse,
|
|
||||||
mockPrivateKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(authReqCryptoService.decryptPubKeyEncryptedMasterKeyAndHash).toBeCalledWith(
|
expect(sut.decryptPubKeyEncryptedMasterKeyAndHash).toBeCalledWith(
|
||||||
mockAuthReqResponse.key,
|
mockAuthReqResponse.key,
|
||||||
mockAuthReqResponse.masterPasswordHash,
|
mockAuthReqResponse.masterPasswordHash,
|
||||||
mockPrivateKey,
|
mockPrivateKey,
|
||||||
@@ -109,7 +138,7 @@ describe("AuthRequestCryptoService", () => {
|
|||||||
cryptoService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedUserKeyBytes);
|
cryptoService.rsaDecrypt.mockResolvedValueOnce(mockDecryptedUserKeyBytes);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await authReqCryptoService.decryptPubKeyEncryptedUserKey(
|
const result = await sut.decryptPubKeyEncryptedUserKey(
|
||||||
mockPubKeyEncryptedUserKey,
|
mockPubKeyEncryptedUserKey,
|
||||||
mockPrivateKey,
|
mockPrivateKey,
|
||||||
);
|
);
|
||||||
@@ -138,7 +167,7 @@ describe("AuthRequestCryptoService", () => {
|
|||||||
.mockResolvedValueOnce(mockDecryptedMasterKeyHashBytes);
|
.mockResolvedValueOnce(mockDecryptedMasterKeyHashBytes);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
const result = await authReqCryptoService.decryptPubKeyEncryptedMasterKeyAndHash(
|
const result = await sut.decryptPubKeyEncryptedMasterKeyAndHash(
|
||||||
mockPubKeyEncryptedMasterKey,
|
mockPubKeyEncryptedMasterKey,
|
||||||
mockPubKeyEncryptedMasterKeyHash,
|
mockPubKeyEncryptedMasterKeyHash,
|
||||||
mockPrivateKey,
|
mockPrivateKey,
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { PasswordlessAuthRequest } from "@bitwarden/common/auth/models/request/passwordless-auth.request";
|
||||||
|
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
||||||
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||||
|
import { MasterKey, UserKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
|
import { AuthRequestServiceAbstraction } from "../../abstractions/auth-request.service.abstraction";
|
||||||
|
|
||||||
|
export class AuthRequestService implements AuthRequestServiceAbstraction {
|
||||||
|
constructor(
|
||||||
|
private appIdService: AppIdService,
|
||||||
|
private cryptoService: CryptoService,
|
||||||
|
private apiService: ApiService,
|
||||||
|
private stateService: StateService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async approveOrDenyAuthRequest(
|
||||||
|
approve: boolean,
|
||||||
|
authRequest: AuthRequestResponse,
|
||||||
|
): Promise<AuthRequestResponse> {
|
||||||
|
if (!authRequest.id) {
|
||||||
|
throw new Error("Auth request has no id");
|
||||||
|
}
|
||||||
|
if (!authRequest.key) {
|
||||||
|
throw new Error("Auth request has no public key");
|
||||||
|
}
|
||||||
|
const pubKey = Utils.fromB64ToArray(authRequest.key);
|
||||||
|
|
||||||
|
const masterKey = await this.cryptoService.getMasterKey();
|
||||||
|
const masterKeyHash = await this.stateService.getKeyHash();
|
||||||
|
let encryptedMasterKeyHash;
|
||||||
|
let keyToEncrypt;
|
||||||
|
|
||||||
|
if (masterKey && masterKeyHash) {
|
||||||
|
// Only encrypt the master password hash if masterKey exists as
|
||||||
|
// we won't have a masterKeyHash without a masterKey
|
||||||
|
encryptedMasterKeyHash = await this.cryptoService.rsaEncrypt(
|
||||||
|
Utils.fromUtf8ToArray(masterKeyHash),
|
||||||
|
pubKey,
|
||||||
|
);
|
||||||
|
keyToEncrypt = masterKey.encKey;
|
||||||
|
} else {
|
||||||
|
const userKey = await this.cryptoService.getUserKey();
|
||||||
|
keyToEncrypt = userKey.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
const encryptedKey = await this.cryptoService.rsaEncrypt(keyToEncrypt, pubKey);
|
||||||
|
|
||||||
|
const response = new PasswordlessAuthRequest(
|
||||||
|
encryptedKey.encryptedString,
|
||||||
|
encryptedMasterKeyHash?.encryptedString,
|
||||||
|
await this.appIdService.getAppId(),
|
||||||
|
approve,
|
||||||
|
);
|
||||||
|
return await this.apiService.putAuthRequest(authRequest.id, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setUserKeyAfterDecryptingSharedUserKey(
|
||||||
|
authReqResponse: AuthRequestResponse,
|
||||||
|
authReqPrivateKey: Uint8Array,
|
||||||
|
) {
|
||||||
|
const userKey = await this.decryptPubKeyEncryptedUserKey(
|
||||||
|
authReqResponse.key,
|
||||||
|
authReqPrivateKey,
|
||||||
|
);
|
||||||
|
await this.cryptoService.setUserKey(userKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setKeysAfterDecryptingSharedMasterKeyAndHash(
|
||||||
|
authReqResponse: AuthRequestResponse,
|
||||||
|
authReqPrivateKey: Uint8Array,
|
||||||
|
) {
|
||||||
|
const { masterKey, masterKeyHash } = await this.decryptPubKeyEncryptedMasterKeyAndHash(
|
||||||
|
authReqResponse.key,
|
||||||
|
authReqResponse.masterPasswordHash,
|
||||||
|
authReqPrivateKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Decrypt and set user key in state
|
||||||
|
const userKey = await this.cryptoService.decryptUserKeyWithMasterKey(masterKey);
|
||||||
|
|
||||||
|
// Set masterKey + masterKeyHash in state after decryption (in case decryption fails)
|
||||||
|
await this.cryptoService.setMasterKey(masterKey);
|
||||||
|
await this.cryptoService.setMasterKeyHash(masterKeyHash);
|
||||||
|
|
||||||
|
await this.cryptoService.setUserKey(userKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decryption helpers
|
||||||
|
async decryptPubKeyEncryptedUserKey(
|
||||||
|
pubKeyEncryptedUserKey: string,
|
||||||
|
privateKey: Uint8Array,
|
||||||
|
): Promise<UserKey> {
|
||||||
|
const decryptedUserKeyBytes = await this.cryptoService.rsaDecrypt(
|
||||||
|
pubKeyEncryptedUserKey,
|
||||||
|
privateKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
return new SymmetricCryptoKey(decryptedUserKeyBytes) as UserKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async decryptPubKeyEncryptedMasterKeyAndHash(
|
||||||
|
pubKeyEncryptedMasterKey: string,
|
||||||
|
pubKeyEncryptedMasterKeyHash: string,
|
||||||
|
privateKey: Uint8Array,
|
||||||
|
): Promise<{ masterKey: MasterKey; masterKeyHash: string }> {
|
||||||
|
const decryptedMasterKeyArrayBuffer = await this.cryptoService.rsaDecrypt(
|
||||||
|
pubKeyEncryptedMasterKey,
|
||||||
|
privateKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
const decryptedMasterKeyHashArrayBuffer = await this.cryptoService.rsaDecrypt(
|
||||||
|
pubKeyEncryptedMasterKeyHash,
|
||||||
|
privateKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
const masterKey = new SymmetricCryptoKey(decryptedMasterKeyArrayBuffer) as MasterKey;
|
||||||
|
const masterKeyHash = Utils.fromBufferToUtf8(decryptedMasterKeyHashArrayBuffer);
|
||||||
|
|
||||||
|
return {
|
||||||
|
masterKey,
|
||||||
|
masterKeyHash,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
export * from "./pin-crypto/pin-crypto.service.implementation";
|
export * from "./pin-crypto/pin-crypto.service.implementation";
|
||||||
export * from "./login-strategies/login-strategy.service";
|
export * from "./login-strategies/login-strategy.service";
|
||||||
|
export * from "./auth-request/auth-request.service";
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Observable, Subject } from "rxjs";
|
|||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
|
||||||
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
|
||||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||||
@@ -11,8 +10,6 @@ import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-
|
|||||||
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
|
||||||
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
import { KdfConfig } from "@bitwarden/common/auth/models/domain/kdf-config";
|
||||||
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
|
||||||
import { PasswordlessAuthRequest } from "@bitwarden/common/auth/models/request/passwordless-auth.request";
|
|
||||||
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
|
|
||||||
import { PreloginRequest } from "@bitwarden/common/models/request/prelogin.request";
|
import { PreloginRequest } from "@bitwarden/common/models/request/prelogin.request";
|
||||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||||
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
|
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
|
||||||
@@ -26,11 +23,10 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
|||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||||
import { KdfType } from "@bitwarden/common/platform/enums";
|
import { KdfType } from "@bitwarden/common/platform/enums";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
|
||||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||||
import { MasterKey } from "@bitwarden/common/types/key";
|
import { MasterKey } from "@bitwarden/common/types/key";
|
||||||
|
|
||||||
import { LoginStrategyServiceAbstraction } from "../../abstractions";
|
import { AuthRequestServiceAbstraction, LoginStrategyServiceAbstraction } from "../../abstractions";
|
||||||
import { AuthRequestLoginStrategy } from "../../login-strategies/auth-request-login.strategy";
|
import { AuthRequestLoginStrategy } from "../../login-strategies/auth-request-login.strategy";
|
||||||
import { PasswordLoginStrategy } from "../../login-strategies/password-login.strategy";
|
import { PasswordLoginStrategy } from "../../login-strategies/password-login.strategy";
|
||||||
import { SsoLoginStrategy } from "../../login-strategies/sso-login.strategy";
|
import { SsoLoginStrategy } from "../../login-strategies/sso-login.strategy";
|
||||||
@@ -110,7 +106,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
|||||||
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
|
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
|
||||||
protected policyService: PolicyService,
|
protected policyService: PolicyService,
|
||||||
protected deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
protected deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
|
||||||
protected authReqCryptoService: AuthRequestCryptoServiceAbstraction,
|
protected authRequestService: AuthRequestServiceAbstraction,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async logIn(
|
async logIn(
|
||||||
@@ -160,7 +156,7 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
|||||||
this.twoFactorService,
|
this.twoFactorService,
|
||||||
this.keyConnectorService,
|
this.keyConnectorService,
|
||||||
this.deviceTrustCryptoService,
|
this.deviceTrustCryptoService,
|
||||||
this.authReqCryptoService,
|
this.authRequestService,
|
||||||
this.i18nService,
|
this.i18nService,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -290,45 +286,6 @@ export class LoginStrategyService implements LoginStrategyServiceAbstraction {
|
|||||||
return this.pushNotificationSubject.asObservable();
|
return this.pushNotificationSubject.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
async passwordlessLogin(
|
|
||||||
id: string,
|
|
||||||
key: string,
|
|
||||||
requestApproved: boolean,
|
|
||||||
): Promise<AuthRequestResponse> {
|
|
||||||
const pubKey = Utils.fromB64ToArray(key);
|
|
||||||
|
|
||||||
const masterKey = await this.cryptoService.getMasterKey();
|
|
||||||
let keyToEncrypt;
|
|
||||||
let encryptedMasterKeyHash = null;
|
|
||||||
|
|
||||||
if (masterKey) {
|
|
||||||
keyToEncrypt = masterKey.encKey;
|
|
||||||
|
|
||||||
// Only encrypt the master password hash if masterKey exists as
|
|
||||||
// we won't have a masterKeyHash without a masterKey
|
|
||||||
const masterKeyHash = await this.stateService.getKeyHash();
|
|
||||||
if (masterKeyHash != null) {
|
|
||||||
encryptedMasterKeyHash = await this.cryptoService.rsaEncrypt(
|
|
||||||
Utils.fromUtf8ToArray(masterKeyHash),
|
|
||||||
pubKey,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const userKey = await this.cryptoService.getUserKey();
|
|
||||||
keyToEncrypt = userKey.key;
|
|
||||||
}
|
|
||||||
|
|
||||||
const encryptedKey = await this.cryptoService.rsaEncrypt(keyToEncrypt, pubKey);
|
|
||||||
|
|
||||||
const request = new PasswordlessAuthRequest(
|
|
||||||
encryptedKey.encryptedString,
|
|
||||||
encryptedMasterKeyHash?.encryptedString,
|
|
||||||
await this.appIdService.getAppId(),
|
|
||||||
requestApproved,
|
|
||||||
);
|
|
||||||
return await this.apiService.putAuthRequest(id, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private saveState(
|
private saveState(
|
||||||
strategy:
|
strategy:
|
||||||
| UserApiLoginStrategy
|
| UserApiLoginStrategy
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
import { UserKey, MasterKey } from "../../types/key";
|
|
||||||
import { AuthRequestResponse } from "../models/response/auth-request.response";
|
|
||||||
|
|
||||||
export abstract class AuthRequestCryptoServiceAbstraction {
|
|
||||||
setUserKeyAfterDecryptingSharedUserKey: (
|
|
||||||
authReqResponse: AuthRequestResponse,
|
|
||||||
authReqPrivateKey: ArrayBuffer,
|
|
||||||
) => Promise<void>;
|
|
||||||
setKeysAfterDecryptingSharedMasterKeyAndHash: (
|
|
||||||
authReqResponse: AuthRequestResponse,
|
|
||||||
authReqPrivateKey: ArrayBuffer,
|
|
||||||
) => Promise<void>;
|
|
||||||
|
|
||||||
decryptPubKeyEncryptedUserKey: (
|
|
||||||
pubKeyEncryptedUserKey: string,
|
|
||||||
privateKey: ArrayBuffer,
|
|
||||||
) => Promise<UserKey>;
|
|
||||||
|
|
||||||
decryptPubKeyEncryptedMasterKeyAndHash: (
|
|
||||||
pubKeyEncryptedMasterKey: string,
|
|
||||||
pubKeyEncryptedMasterKeyHash: string,
|
|
||||||
privateKey: ArrayBuffer,
|
|
||||||
) => Promise<{ masterKey: MasterKey; masterKeyHash: string }>;
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
import { CryptoService } from "../../platform/abstractions/crypto.service";
|
|
||||||
import { Utils } from "../../platform/misc/utils";
|
|
||||||
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key";
|
|
||||||
import { UserKey, MasterKey } from "../../types/key";
|
|
||||||
import { AuthRequestCryptoServiceAbstraction } from "../abstractions/auth-request-crypto.service.abstraction";
|
|
||||||
import { AuthRequestResponse } from "../models/response/auth-request.response";
|
|
||||||
|
|
||||||
export class AuthRequestCryptoServiceImplementation implements AuthRequestCryptoServiceAbstraction {
|
|
||||||
constructor(private cryptoService: CryptoService) {}
|
|
||||||
|
|
||||||
async setUserKeyAfterDecryptingSharedUserKey(
|
|
||||||
authReqResponse: AuthRequestResponse,
|
|
||||||
authReqPrivateKey: Uint8Array,
|
|
||||||
) {
|
|
||||||
const userKey = await this.decryptPubKeyEncryptedUserKey(
|
|
||||||
authReqResponse.key,
|
|
||||||
authReqPrivateKey,
|
|
||||||
);
|
|
||||||
await this.cryptoService.setUserKey(userKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
async setKeysAfterDecryptingSharedMasterKeyAndHash(
|
|
||||||
authReqResponse: AuthRequestResponse,
|
|
||||||
authReqPrivateKey: Uint8Array,
|
|
||||||
) {
|
|
||||||
const { masterKey, masterKeyHash } = await this.decryptPubKeyEncryptedMasterKeyAndHash(
|
|
||||||
authReqResponse.key,
|
|
||||||
authReqResponse.masterPasswordHash,
|
|
||||||
authReqPrivateKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Decrypt and set user key in state
|
|
||||||
const userKey = await this.cryptoService.decryptUserKeyWithMasterKey(masterKey);
|
|
||||||
|
|
||||||
// Set masterKey + masterKeyHash in state after decryption (in case decryption fails)
|
|
||||||
await this.cryptoService.setMasterKey(masterKey);
|
|
||||||
await this.cryptoService.setMasterKeyHash(masterKeyHash);
|
|
||||||
|
|
||||||
await this.cryptoService.setUserKey(userKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decryption helpers
|
|
||||||
async decryptPubKeyEncryptedUserKey(
|
|
||||||
pubKeyEncryptedUserKey: string,
|
|
||||||
privateKey: Uint8Array,
|
|
||||||
): Promise<UserKey> {
|
|
||||||
const decryptedUserKeyBytes = await this.cryptoService.rsaDecrypt(
|
|
||||||
pubKeyEncryptedUserKey,
|
|
||||||
privateKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
return new SymmetricCryptoKey(decryptedUserKeyBytes) as UserKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
async decryptPubKeyEncryptedMasterKeyAndHash(
|
|
||||||
pubKeyEncryptedMasterKey: string,
|
|
||||||
pubKeyEncryptedMasterKeyHash: string,
|
|
||||||
privateKey: Uint8Array,
|
|
||||||
): Promise<{ masterKey: MasterKey; masterKeyHash: string }> {
|
|
||||||
const decryptedMasterKeyArrayBuffer = await this.cryptoService.rsaDecrypt(
|
|
||||||
pubKeyEncryptedMasterKey,
|
|
||||||
privateKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
const decryptedMasterKeyHashArrayBuffer = await this.cryptoService.rsaDecrypt(
|
|
||||||
pubKeyEncryptedMasterKeyHash,
|
|
||||||
privateKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
const masterKey = new SymmetricCryptoKey(decryptedMasterKeyArrayBuffer) as MasterKey;
|
|
||||||
const masterKeyHash = Utils.fromBufferToUtf8(decryptedMasterKeyHashArrayBuffer);
|
|
||||||
|
|
||||||
return {
|
|
||||||
masterKey,
|
|
||||||
masterKeyHash,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user