1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 14:23:32 +00:00

[PM-5255] Create login strategy service (#7750)

* refactor login strategies into own service

* create login service factory

* replaces instances of authService with loginStrategyService

* replace more instances of authService

* move logout back to auth service

* add browser dependencies

* fix desktop dependencies

* fix cli dependencies

* fix lint and test files

* fix anonymous hub deps

* fix webauthn-login service deps

* add loginstrategyservice to bg

* move login strategy service and models to auth folder

* revert changes to tsconfig

* use alias for imports

* fix path

---------

Co-authored-by: rr-bw <102181210+rr-bw@users.noreply.github.com>
This commit is contained in:
Jake Fink
2024-02-05 14:26:41 -05:00
committed by GitHub
parent 568f3ecb2a
commit 816bcf4f39
56 changed files with 1002 additions and 850 deletions

View File

@@ -2,90 +2,34 @@ import { AuthService as AbstractAuthService } from "@bitwarden/common/auth/abstr
import { AuthService } from "@bitwarden/common/auth/services/auth.service"; import { AuthService } from "@bitwarden/common/auth/services/auth.service";
import { import {
policyServiceFactory,
PolicyServiceInitOptions,
} from "../../../admin-console/background/service-factories/policy-service.factory";
import {
apiServiceFactory,
ApiServiceInitOptions, ApiServiceInitOptions,
apiServiceFactory,
} from "../../../platform/background/service-factories/api-service.factory"; } from "../../../platform/background/service-factories/api-service.factory";
import { appIdServiceFactory } from "../../../platform/background/service-factories/app-id-service.factory";
import { import {
CryptoServiceInitOptions, CryptoServiceInitOptions,
cryptoServiceFactory, cryptoServiceFactory,
} from "../../../platform/background/service-factories/crypto-service.factory"; } from "../../../platform/background/service-factories/crypto-service.factory";
import {
EncryptServiceInitOptions,
encryptServiceFactory,
} from "../../../platform/background/service-factories/encrypt-service.factory";
import {
environmentServiceFactory,
EnvironmentServiceInitOptions,
} from "../../../platform/background/service-factories/environment-service.factory";
import { import {
CachedServices, CachedServices,
factory,
FactoryOptions, FactoryOptions,
factory,
} from "../../../platform/background/service-factories/factory-options"; } from "../../../platform/background/service-factories/factory-options";
import {
i18nServiceFactory,
I18nServiceInitOptions,
} from "../../../platform/background/service-factories/i18n-service.factory";
import {
logServiceFactory,
LogServiceInitOptions,
} from "../../../platform/background/service-factories/log-service.factory";
import { import {
messagingServiceFactory, messagingServiceFactory,
MessagingServiceInitOptions, MessagingServiceInitOptions,
} from "../../../platform/background/service-factories/messaging-service.factory"; } from "../../../platform/background/service-factories/messaging-service.factory";
import { import {
platformUtilsServiceFactory,
PlatformUtilsServiceInitOptions,
} from "../../../platform/background/service-factories/platform-utils-service.factory";
import {
stateServiceFactory,
StateServiceInitOptions, StateServiceInitOptions,
stateServiceFactory,
} from "../../../platform/background/service-factories/state-service.factory"; } from "../../../platform/background/service-factories/state-service.factory";
import {
passwordStrengthServiceFactory,
PasswordStrengthServiceInitOptions,
} from "../../../tools/background/service_factories/password-strength-service.factory";
import { type AuthServiceFactoryOptions = FactoryOptions;
authRequestCryptoServiceFactory,
AuthRequestCryptoServiceInitOptions,
} from "./auth-request-crypto-service.factory";
import {
deviceTrustCryptoServiceFactory,
DeviceTrustCryptoServiceInitOptions,
} from "./device-trust-crypto-service.factory";
import {
keyConnectorServiceFactory,
KeyConnectorServiceInitOptions,
} from "./key-connector-service.factory";
import { tokenServiceFactory, TokenServiceInitOptions } from "./token-service.factory";
import { twoFactorServiceFactory, TwoFactorServiceInitOptions } from "./two-factor-service.factory";
type AuthServiceFactoyOptions = FactoryOptions; export type AuthServiceInitOptions = AuthServiceFactoryOptions &
MessagingServiceInitOptions &
export type AuthServiceInitOptions = AuthServiceFactoyOptions &
CryptoServiceInitOptions & CryptoServiceInitOptions &
ApiServiceInitOptions & ApiServiceInitOptions &
TokenServiceInitOptions & StateServiceInitOptions;
PlatformUtilsServiceInitOptions &
MessagingServiceInitOptions &
LogServiceInitOptions &
KeyConnectorServiceInitOptions &
EnvironmentServiceInitOptions &
StateServiceInitOptions &
TwoFactorServiceInitOptions &
I18nServiceInitOptions &
EncryptServiceInitOptions &
PolicyServiceInitOptions &
PasswordStrengthServiceInitOptions &
DeviceTrustCryptoServiceInitOptions &
AuthRequestCryptoServiceInitOptions;
export function authServiceFactory( export function authServiceFactory(
cache: { authService?: AbstractAuthService } & CachedServices, cache: { authService?: AbstractAuthService } & CachedServices,
@@ -97,23 +41,10 @@ export function authServiceFactory(
opts, opts,
async () => async () =>
new AuthService( new AuthService(
await messagingServiceFactory(cache, opts),
await cryptoServiceFactory(cache, opts), await cryptoServiceFactory(cache, opts),
await apiServiceFactory(cache, opts), await apiServiceFactory(cache, opts),
await tokenServiceFactory(cache, opts),
await appIdServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts),
await messagingServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await keyConnectorServiceFactory(cache, opts),
await environmentServiceFactory(cache, opts),
await stateServiceFactory(cache, opts), await stateServiceFactory(cache, opts),
await twoFactorServiceFactory(cache, opts),
await i18nServiceFactory(cache, opts),
await encryptServiceFactory(cache, opts),
await passwordStrengthServiceFactory(cache, opts),
await policyServiceFactory(cache, opts),
await deviceTrustCryptoServiceFactory(cache, opts),
await authRequestCryptoServiceFactory(cache, opts),
), ),
); );
} }

View File

@@ -0,0 +1,118 @@
import { LoginStrategyService, LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import {
policyServiceFactory,
PolicyServiceInitOptions,
} from "../../../admin-console/background/service-factories/policy-service.factory";
import {
apiServiceFactory,
ApiServiceInitOptions,
} from "../../../platform/background/service-factories/api-service.factory";
import { appIdServiceFactory } from "../../../platform/background/service-factories/app-id-service.factory";
import {
CryptoServiceInitOptions,
cryptoServiceFactory,
} from "../../../platform/background/service-factories/crypto-service.factory";
import {
EncryptServiceInitOptions,
encryptServiceFactory,
} from "../../../platform/background/service-factories/encrypt-service.factory";
import {
environmentServiceFactory,
EnvironmentServiceInitOptions,
} from "../../../platform/background/service-factories/environment-service.factory";
import {
CachedServices,
factory,
FactoryOptions,
} from "../../../platform/background/service-factories/factory-options";
import {
i18nServiceFactory,
I18nServiceInitOptions,
} from "../../../platform/background/service-factories/i18n-service.factory";
import {
logServiceFactory,
LogServiceInitOptions,
} from "../../../platform/background/service-factories/log-service.factory";
import {
messagingServiceFactory,
MessagingServiceInitOptions,
} from "../../../platform/background/service-factories/messaging-service.factory";
import {
platformUtilsServiceFactory,
PlatformUtilsServiceInitOptions,
} from "../../../platform/background/service-factories/platform-utils-service.factory";
import {
stateServiceFactory,
StateServiceInitOptions,
} from "../../../platform/background/service-factories/state-service.factory";
import {
passwordStrengthServiceFactory,
PasswordStrengthServiceInitOptions,
} from "../../../tools/background/service_factories/password-strength-service.factory";
import {
authRequestCryptoServiceFactory,
AuthRequestCryptoServiceInitOptions,
} from "./auth-request-crypto-service.factory";
import {
deviceTrustCryptoServiceFactory,
DeviceTrustCryptoServiceInitOptions,
} from "./device-trust-crypto-service.factory";
import {
keyConnectorServiceFactory,
KeyConnectorServiceInitOptions,
} from "./key-connector-service.factory";
import { tokenServiceFactory, TokenServiceInitOptions } from "./token-service.factory";
import { twoFactorServiceFactory, TwoFactorServiceInitOptions } from "./two-factor-service.factory";
type LoginStrategyServiceFactoryOptions = FactoryOptions;
export type LoginStrategyServiceInitOptions = LoginStrategyServiceFactoryOptions &
CryptoServiceInitOptions &
ApiServiceInitOptions &
TokenServiceInitOptions &
PlatformUtilsServiceInitOptions &
MessagingServiceInitOptions &
LogServiceInitOptions &
KeyConnectorServiceInitOptions &
EnvironmentServiceInitOptions &
StateServiceInitOptions &
TwoFactorServiceInitOptions &
I18nServiceInitOptions &
EncryptServiceInitOptions &
PolicyServiceInitOptions &
PasswordStrengthServiceInitOptions &
DeviceTrustCryptoServiceInitOptions &
AuthRequestCryptoServiceInitOptions;
export function loginStrategyServiceFactory(
cache: { loginStrategyService?: LoginStrategyServiceAbstraction } & CachedServices,
opts: LoginStrategyServiceInitOptions,
): Promise<LoginStrategyServiceAbstraction> {
return factory(
cache,
"loginStrategyService",
opts,
async () =>
new LoginStrategyService(
await cryptoServiceFactory(cache, opts),
await apiServiceFactory(cache, opts),
await tokenServiceFactory(cache, opts),
await appIdServiceFactory(cache, opts),
await platformUtilsServiceFactory(cache, opts),
await messagingServiceFactory(cache, opts),
await logServiceFactory(cache, opts),
await keyConnectorServiceFactory(cache, opts),
await environmentServiceFactory(cache, opts),
await stateServiceFactory(cache, opts),
await twoFactorServiceFactory(cache, opts),
await i18nServiceFactory(cache, opts),
await encryptServiceFactory(cache, opts),
await passwordStrengthServiceFactory(cache, opts),
await policyServiceFactory(cache, opts),
await deviceTrustCryptoServiceFactory(cache, opts),
await authRequestCryptoServiceFactory(cache, opts),
),
);
}

View File

@@ -3,6 +3,7 @@ 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 { 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 { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
@@ -48,6 +49,7 @@ export class LoginViaAuthRequestComponent
syncService: SyncService, syncService: SyncService,
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
authReqCryptoService: AuthRequestCryptoServiceAbstraction, authReqCryptoService: AuthRequestCryptoServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
private location: Location, private location: Location,
) { ) {
super( super(
@@ -68,6 +70,7 @@ export class LoginViaAuthRequestComponent
loginService, loginService,
deviceTrustCryptoService, deviceTrustCryptoService,
authReqCryptoService, authReqCryptoService,
loginStrategyService,
); );
super.onSuccessfulLogin = async () => { super.onSuccessfulLogin = async () => {
await syncService.fullSync(true); await syncService.fullSync(true);

View File

@@ -4,7 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component"; import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service"; import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction"; import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction"; import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
@@ -30,7 +30,7 @@ export class LoginComponent extends BaseLoginComponent {
constructor( constructor(
devicesApiService: DevicesApiServiceAbstraction, devicesApiService: DevicesApiServiceAbstraction,
appIdService: AppIdService, appIdService: AppIdService,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
protected platformUtilsService: PlatformUtilsService, protected platformUtilsService: PlatformUtilsService,
protected i18nService: I18nService, protected i18nService: I18nService,
@@ -50,7 +50,7 @@ export class LoginComponent extends BaseLoginComponent {
super( super(
devicesApiService, devicesApiService,
appIdService, appIdService,
authService, loginStrategyService,
router, router,
platformUtilsService, platformUtilsService,
i18nService, i18nService,

View File

@@ -4,9 +4,9 @@ import { Router } from "@angular/router";
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/auth/components/register.component"; import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/auth/components/register.component";
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service"; import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
import { 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 { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -27,7 +27,7 @@ export class RegisterComponent extends BaseRegisterComponent {
constructor( constructor(
formValidationErrorService: FormValidationErrorsService, formValidationErrorService: FormValidationErrorsService,
formBuilder: UntypedFormBuilder, formBuilder: UntypedFormBuilder,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
cryptoService: CryptoService, cryptoService: CryptoService,
@@ -43,7 +43,7 @@ export class RegisterComponent extends BaseRegisterComponent {
super( super(
formValidationErrorService, formValidationErrorService,
formBuilder, formBuilder,
authService, loginStrategyService,
router, router,
i18nService, i18nService,
cryptoService, cryptoService,

View File

@@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component"; import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
@@ -24,7 +25,7 @@ import { BrowserApi } from "../../platform/browser/browser-api";
}) })
export class SsoComponent extends BaseSsoComponent { export class SsoComponent extends BaseSsoComponent {
constructor( constructor(
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
route: ActivatedRoute, route: ActivatedRoute,
@@ -37,10 +38,11 @@ export class SsoComponent extends BaseSsoComponent {
environmentService: EnvironmentService, environmentService: EnvironmentService,
logService: LogService, logService: LogService,
configService: ConfigServiceAbstraction, configService: ConfigServiceAbstraction,
protected authService: AuthService,
@Inject(WINDOW) private win: Window, @Inject(WINDOW) private win: Window,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
route, route,

View File

@@ -5,8 +5,8 @@ import { filter, first, takeUntil } from "rxjs/operators";
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component"; import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
@@ -39,7 +39,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
inPopout = BrowserPopupUtils.inPopout(window); inPopout = BrowserPopupUtils.inPopout(window);
constructor( constructor(
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
apiService: ApiService, apiService: ApiService,
@@ -60,7 +60,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
private browserMessagingApi: ZonedMessageListenerService, private browserMessagingApi: ZonedMessageListenerService,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
apiService, apiService,

View File

@@ -1,4 +1,9 @@
import { PinCryptoServiceAbstraction, PinCryptoService } from "@bitwarden/auth/common"; import {
PinCryptoServiceAbstraction,
PinCryptoService,
LoginStrategyServiceAbstraction,
LoginStrategyService,
} 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";
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service"; import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
@@ -214,6 +219,7 @@ export default class MainBackground {
containerService: ContainerService; containerService: ContainerService;
auditService: AuditServiceAbstraction; auditService: AuditServiceAbstraction;
authService: AuthServiceAbstraction; authService: AuthServiceAbstraction;
loginStrategyService: LoginStrategyServiceAbstraction;
importApiService: ImportApiServiceAbstraction; importApiService: ImportApiServiceAbstraction;
importService: ImportServiceAbstraction; importService: ImportServiceAbstraction;
exportService: VaultExportServiceAbstraction; exportService: VaultExportServiceAbstraction;
@@ -490,6 +496,13 @@ export default class MainBackground {
this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService); this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService);
this.authService = new AuthService( this.authService = new AuthService(
backgroundMessagingService,
this.cryptoService,
this.apiService,
this.stateService,
);
this.loginStrategyService = new LoginStrategyService(
this.cryptoService, this.cryptoService,
this.apiService, this.apiService,
this.tokenService, this.tokenService,

View File

@@ -10,6 +10,7 @@ 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 { 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";
@@ -181,6 +182,10 @@ function getBgService<T>(service: keyof MainBackground) {
useFactory: getBgService<AuthService>("authService"), useFactory: getBgService<AuthService>("authService"),
deps: [], deps: [],
}, },
{
provide: LoginStrategyServiceAbstraction,
useFactory: getBgService<LoginStrategyServiceAbstraction>("loginStrategyService"),
},
{ {
provide: SearchServiceAbstraction, provide: SearchServiceAbstraction,
useFactory: (logService: ConsoleLogService, i18nService: I18nServiceAbstraction) => { useFactory: (logService: ConsoleLogService, i18nService: I18nServiceAbstraction) => {

View File

@@ -5,6 +5,12 @@ import * as inquirer from "inquirer";
import Separator from "inquirer/lib/objects/separator"; import Separator from "inquirer/lib/objects/separator";
import { firstValueFrom } from "rxjs"; import { firstValueFrom } from "rxjs";
import {
LoginStrategyServiceAbstraction,
PasswordLoginCredentials,
SsoLoginCredentials,
UserApiLoginCredentials,
} from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
@@ -15,11 +21,6 @@ import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
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 {
PasswordLoginCredentials,
SsoLoginCredentials,
UserApiLoginCredentials,
} from "@bitwarden/common/auth/models/domain/login-credentials";
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 { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request"; import { PasswordRequest } from "@bitwarden/common/auth/models/request/password.request";
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request"; import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
@@ -50,6 +51,7 @@ export class LoginCommand {
private options: OptionValues; private options: OptionValues;
constructor( constructor(
protected loginStrategyService: LoginStrategyServiceAbstraction,
protected authService: AuthService, protected authService: AuthService,
protected apiService: ApiService, protected apiService: ApiService,
protected cryptoFunctionService: CryptoFunctionService, protected cryptoFunctionService: CryptoFunctionService,
@@ -178,7 +180,7 @@ export class LoginCommand {
return Response.error("Invalid API Key; Organization API Key currently not supported"); return Response.error("Invalid API Key; Organization API Key currently not supported");
} }
try { try {
response = await this.authService.logIn( response = await this.loginStrategyService.logIn(
new UserApiLoginCredentials(clientId, clientSecret), new UserApiLoginCredentials(clientId, clientSecret),
); );
} catch (e) { } catch (e) {
@@ -195,7 +197,7 @@ export class LoginCommand {
throw e; throw e;
} }
} else if (ssoCode != null && ssoCodeVerifier != null) { } else if (ssoCode != null && ssoCodeVerifier != null) {
response = await this.authService.logIn( response = await this.loginStrategyService.logIn(
new SsoLoginCredentials( new SsoLoginCredentials(
ssoCode, ssoCode,
ssoCodeVerifier, ssoCodeVerifier,
@@ -205,7 +207,7 @@ export class LoginCommand {
), ),
); );
} else { } else {
response = await this.authService.logIn( response = await this.loginStrategyService.logIn(
new PasswordLoginCredentials(email, password, null, twoFactor), new PasswordLoginCredentials(email, password, null, twoFactor),
); );
} }
@@ -271,8 +273,8 @@ export class LoginCommand {
selectedProvider.type === TwoFactorProviderType.Email selectedProvider.type === TwoFactorProviderType.Email
) { ) {
const emailReq = new TwoFactorEmailRequest(); const emailReq = new TwoFactorEmailRequest();
emailReq.email = this.authService.email; emailReq.email = this.loginStrategyService.email;
emailReq.masterPasswordHash = this.authService.masterPasswordHash; emailReq.masterPasswordHash = this.loginStrategyService.masterPasswordHash;
await this.apiService.postTwoFactorEmail(emailReq); await this.apiService.postTwoFactorEmail(emailReq);
} }
@@ -292,7 +294,7 @@ export class LoginCommand {
} }
} }
response = await this.authService.logInTwoFactor( response = await this.loginStrategyService.logInTwoFactor(
new TokenTwoFactorRequest(selectedProvider.type, twoFactorToken), new TokenTwoFactorRequest(selectedProvider.type, twoFactorToken),
null, null,
); );
@@ -604,9 +606,9 @@ export class LoginCommand {
if (credentials != null) { if (credentials != null) {
credentials.captchaToken = captchaClientSecret; credentials.captchaToken = captchaClientSecret;
credentials.twoFactor = twoFactorRequest; credentials.twoFactor = twoFactorRequest;
authResultResponse = await this.authService.logIn(credentials); authResultResponse = await this.loginStrategyService.logIn(credentials);
} else { } else {
authResultResponse = await this.authService.logInTwoFactor( authResultResponse = await this.loginStrategyService.logInTwoFactor(
twoFactorRequest, twoFactorRequest,
captchaClientSecret, captchaClientSecret,
); );

View File

@@ -4,7 +4,12 @@ import * as path from "path";
import { program } from "commander"; import { program } from "commander";
import * as jsdom from "jsdom"; import * as jsdom from "jsdom";
import { PinCryptoServiceAbstraction, PinCryptoService } from "@bitwarden/auth/common"; import {
LoginStrategyService,
LoginStrategyServiceAbstraction,
PinCryptoService,
PinCryptoServiceAbstraction,
} from "@bitwarden/auth/common";
import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service"; import { EventCollectionService as EventCollectionServiceAbstraction } from "@bitwarden/common/abstractions/event/event-collection.service";
import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service"; import { EventUploadService as EventUploadServiceAbstraction } from "@bitwarden/common/abstractions/event/event-upload.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
@@ -191,6 +196,7 @@ export class Main {
activeUserStateProvider: ActiveUserStateProvider; activeUserStateProvider: ActiveUserStateProvider;
derivedStateProvider: DerivedStateProvider; derivedStateProvider: DerivedStateProvider;
stateProvider: StateProvider; stateProvider: StateProvider;
loginStrategyService: LoginStrategyServiceAbstraction;
constructor() { constructor() {
let p = null; let p = null;
@@ -393,7 +399,7 @@ export class Main {
this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService); this.authRequestCryptoService = new AuthRequestCryptoServiceImplementation(this.cryptoService);
this.authService = new AuthService( this.loginStrategyService = new LoginStrategyService(
this.cryptoService, this.cryptoService,
this.apiService, this.apiService,
this.tokenService, this.tokenService,
@@ -413,6 +419,13 @@ export class Main {
this.authRequestCryptoService, this.authRequestCryptoService,
); );
this.authService = new AuthService(
this.messagingService,
this.cryptoService,
this.apiService,
this.stateService,
);
this.configApiService = new ConfigApiService(this.apiService, this.authService); this.configApiService = new ConfigApiService(this.apiService, this.authService);
this.configService = new CliConfigService( this.configService = new CliConfigService(

View File

@@ -139,6 +139,7 @@ export class Program {
if (!options.check) { if (!options.check) {
await this.exitIfAuthed(); await this.exitIfAuthed();
const command = new LoginCommand( const command = new LoginCommand(
this.main.loginStrategyService,
this.main.authService, this.main.authService,
this.main.apiService, this.main.apiService,
this.main.cryptoFunctionService, this.main.cryptoFunctionService,

View File

@@ -4,8 +4,8 @@ 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 { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.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";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
@@ -50,7 +50,7 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
protected platformUtilsService: PlatformUtilsService, protected platformUtilsService: PlatformUtilsService,
protected i18nService: I18nService, protected i18nService: I18nService,
protected apiService: ApiService, protected apiService: ApiService,
protected authService: AuthService, protected loginStrategyService: LoginStrategyServiceAbstraction,
protected appIdService: AppIdService, protected appIdService: AppIdService,
protected cryptoService: CryptoService, protected cryptoService: CryptoService,
private dialogRef: DialogRef, private dialogRef: DialogRef,
@@ -121,7 +121,7 @@ export class LoginApprovalComponent implements OnInit, OnDestroy {
this.i18nService.t("thisRequestIsNoLongerValid"), this.i18nService.t("thisRequestIsNoLongerValid"),
); );
} else { } else {
const loginResponse = await this.authService.passwordlessLogin( const loginResponse = await this.loginStrategyService.passwordlessLogin(
this.authRequestResponse.id, this.authRequestResponse.id,
this.authRequestResponse.publicKey, this.authRequestResponse.publicKey,
approve, approve,

View File

@@ -4,6 +4,7 @@ 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 { 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 { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
@@ -56,6 +57,7 @@ export class LoginViaAuthRequestComponent
loginService: LoginService, loginService: LoginService,
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
authReqCryptoService: AuthRequestCryptoServiceAbstraction, authReqCryptoService: AuthRequestCryptoServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
private location: Location, private location: Location,
) { ) {
super( super(
@@ -76,6 +78,7 @@ export class LoginViaAuthRequestComponent
loginService, loginService,
deviceTrustCryptoService, deviceTrustCryptoService,
authReqCryptoService, authReqCryptoService,
loginStrategyService,
); );
super.onSuccessfulLogin = () => { super.onSuccessfulLogin = () => {

View File

@@ -7,7 +7,7 @@ import { EnvironmentSelectorComponent } from "@bitwarden/angular/auth/components
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component"; import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service"; import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ModalService } from "@bitwarden/angular/services/modal.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction"; import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction"; import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
@@ -55,7 +55,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
constructor( constructor(
devicesApiService: DevicesApiServiceAbstraction, devicesApiService: DevicesApiServiceAbstraction,
appIdService: AppIdService, appIdService: AppIdService,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
syncService: SyncService, syncService: SyncService,
@@ -78,7 +78,7 @@ export class LoginComponent extends BaseLoginComponent implements OnDestroy {
super( super(
devicesApiService, devicesApiService,
appIdService, appIdService,
authService, loginStrategyService,
router, router,
platformUtilsService, platformUtilsService,
i18nService, i18nService,

View File

@@ -4,9 +4,9 @@ import { Router } from "@angular/router";
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/auth/components/register.component"; import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/auth/components/register.component";
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service"; import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
import { 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 { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -27,7 +27,7 @@ export class RegisterComponent extends BaseRegisterComponent implements OnInit,
constructor( constructor(
formValidationErrorService: FormValidationErrorsService, formValidationErrorService: FormValidationErrorsService,
formBuilder: UntypedFormBuilder, formBuilder: UntypedFormBuilder,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
cryptoService: CryptoService, cryptoService: CryptoService,
@@ -45,7 +45,7 @@ export class RegisterComponent extends BaseRegisterComponent implements OnInit,
super( super(
formValidationErrorService, formValidationErrorService,
formBuilder, formBuilder,
authService, loginStrategyService,
router, router,
i18nService, i18nService,
cryptoService, cryptoService,

View File

@@ -2,8 +2,8 @@ import { Component } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component"; import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -20,7 +20,7 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv
}) })
export class SsoComponent extends BaseSsoComponent { export class SsoComponent extends BaseSsoComponent {
constructor( constructor(
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
syncService: SyncService, syncService: SyncService,
@@ -35,7 +35,7 @@ export class SsoComponent extends BaseSsoComponent {
configService: ConfigServiceAbstraction, configService: ConfigServiceAbstraction,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
route, route,

View File

@@ -4,8 +4,8 @@ import { ActivatedRoute, Router } from "@angular/router";
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component"; import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ModalService } from "@bitwarden/angular/services/modal.service";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
@@ -32,7 +32,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
showingModal = false; showingModal = false;
constructor( constructor(
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
apiService: ApiService, apiService: ApiService,
@@ -50,7 +50,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
@Inject(WINDOW) protected win: Window, @Inject(WINDOW) protected win: Window,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
apiService, apiService,

View File

@@ -2,6 +2,7 @@ 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 { 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 { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
@@ -46,6 +47,7 @@ export class LoginViaAuthRequestComponent
loginService: LoginService, loginService: LoginService,
deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
authReqCryptoService: AuthRequestCryptoServiceAbstraction, authReqCryptoService: AuthRequestCryptoServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
) { ) {
super( super(
router, router,
@@ -65,6 +67,7 @@ export class LoginViaAuthRequestComponent
loginService, loginService,
deviceTrustCryptoService, deviceTrustCryptoService,
authReqCryptoService, authReqCryptoService,
loginStrategyService,
); );
} }
} }

View File

@@ -6,13 +6,13 @@ import { first } from "rxjs/operators";
import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component"; import { LoginComponent as BaseLoginComponent } from "@bitwarden/angular/auth/components/login.component";
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service"; import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction"; import { PolicyApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/policy/policy-api.service.abstraction";
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data"; import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options"; import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy"; import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response"; import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction"; import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction"; import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
@@ -45,7 +45,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
constructor( constructor(
devicesApiService: DevicesApiServiceAbstraction, devicesApiService: DevicesApiServiceAbstraction,
appIdService: AppIdService, appIdService: AppIdService,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
route: ActivatedRoute, route: ActivatedRoute,
@@ -69,7 +69,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
super( super(
devicesApiService, devicesApiService,
appIdService, appIdService,
authService, loginStrategyService,
router, router,
platformUtilsService, platformUtilsService,
i18nService, i18nService,

View File

@@ -1,8 +1,8 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
import { Router } from "@angular/router"; import { Router } from "@angular/router";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { TwoFactorRecoveryRequest } from "@bitwarden/common/auth/models/request/two-factor-recovery.request"; import { TwoFactorRecoveryRequest } from "@bitwarden/common/auth/models/request/two-factor-recovery.request";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -25,7 +25,7 @@ export class RecoverTwoFactorComponent {
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService, private i18nService: I18nService,
private cryptoService: CryptoService, private cryptoService: CryptoService,
private authService: AuthService, private loginStrategyService: LoginStrategyServiceAbstraction,
private logService: LogService, private logService: LogService,
) {} ) {}
@@ -34,7 +34,10 @@ export class RecoverTwoFactorComponent {
const request = new TwoFactorRecoveryRequest(); const request = new TwoFactorRecoveryRequest();
request.recoveryCode = this.recoveryCode.replace(/\s/g, "").toLowerCase(); request.recoveryCode = this.recoveryCode.replace(/\s/g, "").toLowerCase();
request.email = this.email.trim().toLowerCase(); request.email = this.email.trim().toLowerCase();
const key = await this.authService.makePreloginKey(this.masterPassword, request.email); const key = await this.loginStrategyService.makePreloginKey(
this.masterPassword,
request.email,
);
request.masterPasswordHash = await this.cryptoService.hashMasterKey(this.masterPassword, key); request.masterPasswordHash = await this.cryptoService.hashMasterKey(this.masterPassword, key);
this.formPromise = this.apiService.postTwoFactorRecover(request); this.formPromise = this.apiService.postTwoFactorRecover(request);
await this.formPromise; await this.formPromise;

View File

@@ -4,11 +4,11 @@ import { Router } from "@angular/router";
import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/auth/components/register.component"; import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/auth/components/register.component";
import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service"; import { FormValidationErrorsService } from "@bitwarden/angular/platform/abstractions/form-validation-errors.service";
import { 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 { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options"; import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request"; import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -35,7 +35,7 @@ export class RegisterFormComponent extends BaseRegisterComponent {
constructor( constructor(
formValidationErrorService: FormValidationErrorsService, formValidationErrorService: FormValidationErrorsService,
formBuilder: UntypedFormBuilder, formBuilder: UntypedFormBuilder,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
cryptoService: CryptoService, cryptoService: CryptoService,
@@ -52,7 +52,7 @@ export class RegisterFormComponent extends BaseRegisterComponent {
super( super(
formValidationErrorService, formValidationErrorService,
formBuilder, formBuilder,
authService, loginStrategyService,
router, router,
i18nService, i18nService,
cryptoService, cryptoService,

View File

@@ -3,10 +3,10 @@ import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs/operators"; import { first } from "rxjs/operators";
import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component"; import { SsoComponent as BaseSsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction"; import { OrgDomainApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization-domain/org-domain-api.service.abstraction";
import { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/organization-domain-sso-details.response"; import { OrganizationDomainSsoDetailsResponse } from "@bitwarden/common/admin-console/abstractions/organization-domain/responses/organization-domain-sso-details.response";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { HttpStatusCode } from "@bitwarden/common/enums"; import { HttpStatusCode } from "@bitwarden/common/enums";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
@@ -26,7 +26,7 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/ge
// eslint-disable-next-line rxjs-angular/prefer-takeuntil // eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class SsoComponent extends BaseSsoComponent { export class SsoComponent extends BaseSsoComponent {
constructor( constructor(
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
route: ActivatedRoute, route: ActivatedRoute,
@@ -42,7 +42,7 @@ export class SsoComponent extends BaseSsoComponent {
configService: ConfigServiceAbstraction, configService: ConfigServiceAbstraction,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
route, route,

View File

@@ -4,8 +4,8 @@ import { ActivatedRoute, Router } from "@angular/router";
import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component"; import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { ModalService } from "@bitwarden/angular/services/modal.service"; import { ModalService } from "@bitwarden/angular/services/modal.service";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
@@ -30,7 +30,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
twoFactorOptionsModal: ViewContainerRef; twoFactorOptionsModal: ViewContainerRef;
constructor( constructor(
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
i18nService: I18nService, i18nService: I18nService,
apiService: ApiService, apiService: ApiService,
@@ -47,7 +47,7 @@ export class TwoFactorComponent extends BaseTwoFactorComponent implements OnDest
@Inject(WINDOW) protected win: Window, @Inject(WINDOW) protected win: Window,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
apiService, apiService,

View File

@@ -2,9 +2,9 @@ import { AfterContentInit, Directive, HostListener, Input } from "@angular/core"
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { SsoComponent } from "@bitwarden/angular/auth/components/sso.component"; import { SsoComponent } from "@bitwarden/angular/auth/components/sso.component";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -31,7 +31,7 @@ export class LinkSsoDirective extends SsoComponent implements AfterContentInit {
platformUtilsService: PlatformUtilsService, platformUtilsService: PlatformUtilsService,
i18nService: I18nService, i18nService: I18nService,
apiService: ApiService, apiService: ApiService,
authService: AuthService, loginStrategyService: LoginStrategyServiceAbstraction,
router: Router, router: Router,
route: ActivatedRoute, route: ActivatedRoute,
cryptoFunctionService: CryptoFunctionService, cryptoFunctionService: CryptoFunctionService,
@@ -42,7 +42,7 @@ export class LinkSsoDirective extends SsoComponent implements AfterContentInit {
configService: ConfigServiceAbstraction, configService: ConfigServiceAbstraction,
) { ) {
super( super(
authService, loginStrategyService,
router, router,
i18nService, i18nService,
route, route,

View File

@@ -2,6 +2,10 @@ import { Directive, OnDestroy, OnInit } from "@angular/core";
import { IsActiveMatchOptions, Router } from "@angular/router"; import { IsActiveMatchOptions, Router } from "@angular/router";
import { Subject, takeUntil } from "rxjs"; import { Subject, takeUntil } from "rxjs";
import {
AuthRequestLoginCredentials,
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 { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
@@ -13,7 +17,6 @@ import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authenticatio
import { AdminAuthRequestStorable } from "@bitwarden/common/auth/models/domain/admin-auth-req-storable"; import { AdminAuthRequestStorable } from "@bitwarden/common/auth/models/domain/admin-auth-req-storable";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
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 { AuthRequestLoginCredentials } from "@bitwarden/common/auth/models/domain/login-credentials";
import { CreateAuthRequest } from "@bitwarden/common/auth/models/request/create-auth.request"; import { CreateAuthRequest } from "@bitwarden/common/auth/models/request/create-auth.request";
import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response"; import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
import { HttpStatusCode } from "@bitwarden/common/enums/http-status-code.enum"; import { HttpStatusCode } from "@bitwarden/common/enums/http-status-code.enum";
@@ -84,6 +87,7 @@ export class LoginViaAuthRequestComponent
private loginService: LoginService, private loginService: LoginService,
private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction, private deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
private authReqCryptoService: AuthRequestCryptoServiceAbstraction, private authReqCryptoService: AuthRequestCryptoServiceAbstraction,
private loginStrategyService: LoginStrategyServiceAbstraction,
) { ) {
super(environmentService, i18nService, platformUtilsService); super(environmentService, i18nService, platformUtilsService);
@@ -95,7 +99,7 @@ export class LoginViaAuthRequestComponent
} }
//gets signalR push notification //gets signalR push notification
this.authService this.loginStrategyService
.getPushNotificationObs$() .getPushNotificationObs$()
.pipe(takeUntil(this.destroy$)) .pipe(takeUntil(this.destroy$))
.subscribe((id) => { .subscribe((id) => {
@@ -438,7 +442,7 @@ export class LoginViaAuthRequestComponent
const credentials = await this.buildAuthRequestLoginCredentials(requestId, authReqResponse); const credentials = await this.buildAuthRequestLoginCredentials(requestId, authReqResponse);
// Note: keys are set by AuthRequestLoginStrategy success handling // Note: keys are set by AuthRequestLoginStrategy success handling
return await this.authService.logIn(credentials); return await this.loginStrategyService.logIn(credentials);
} }
// Routing logic // Routing logic

View File

@@ -4,13 +4,12 @@ import { ActivatedRoute, Router } from "@angular/router";
import { Observable, Subject } from "rxjs"; import { Observable, Subject } from "rxjs";
import { take, takeUntil } from "rxjs/operators"; import { take, takeUntil } from "rxjs/operators";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { LoginStrategyServiceAbstraction, PasswordLoginCredentials } from "@bitwarden/auth/common";
import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction"; import { DevicesApiServiceAbstraction } from "@bitwarden/common/auth/abstractions/devices-api.service.abstraction";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction"; import { WebAuthnLoginServiceAbstraction } from "@bitwarden/common/auth/abstractions/webauthn/webauthn-login.service.abstraction";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
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 { PasswordLoginCredentials } from "@bitwarden/common/auth/models/domain/login-credentials";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service"; import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -65,7 +64,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
constructor( constructor(
protected devicesApiService: DevicesApiServiceAbstraction, protected devicesApiService: DevicesApiServiceAbstraction,
protected appIdService: AppIdService, protected appIdService: AppIdService,
protected authService: AuthService, protected loginStrategyService: LoginStrategyServiceAbstraction,
protected router: Router, protected router: Router,
platformUtilsService: PlatformUtilsService, platformUtilsService: PlatformUtilsService,
i18nService: I18nService, i18nService: I18nService,
@@ -151,7 +150,7 @@ export class LoginComponent extends CaptchaProtectedComponent implements OnInit,
this.captchaToken, this.captchaToken,
null, null,
); );
this.formPromise = this.authService.logIn(credentials); this.formPromise = this.loginStrategyService.logIn(credentials);
const response = await this.formPromise; const response = await this.formPromise;
this.setFormValues(); this.setFormValues();
await this.loginService.saveEmailSettings(); await this.loginService.saveEmailSettings();

View File

@@ -2,10 +2,9 @@ import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core";
import { AbstractControl, UntypedFormBuilder, ValidatorFn, Validators } from "@angular/forms"; import { AbstractControl, UntypedFormBuilder, ValidatorFn, Validators } from "@angular/forms";
import { Router } from "@angular/router"; import { Router } from "@angular/router";
import { LoginStrategyServiceAbstraction, PasswordLoginCredentials } 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 { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { PasswordLoginCredentials } from "@bitwarden/common/auth/models/domain/login-credentials";
import { RegisterResponse } from "@bitwarden/common/auth/models/response/register.response"; import { RegisterResponse } from "@bitwarden/common/auth/models/response/register.response";
import { KeysRequest } from "@bitwarden/common/models/request/keys.request"; import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request"; import { ReferenceEventRequest } from "@bitwarden/common/models/request/reference-event.request";
@@ -82,7 +81,7 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
constructor( constructor(
protected formValidationErrorService: FormValidationErrorsService, protected formValidationErrorService: FormValidationErrorsService,
protected formBuilder: UntypedFormBuilder, protected formBuilder: UntypedFormBuilder,
protected authService: AuthService, protected loginStrategyService: LoginStrategyServiceAbstraction,
protected router: Router, protected router: Router,
i18nService: I18nService, i18nService: I18nService,
protected cryptoService: CryptoService, protected cryptoService: CryptoService,
@@ -333,7 +332,7 @@ export class RegisterComponent extends CaptchaProtectedComponent implements OnIn
captchaBypassToken, captchaBypassToken,
null, null,
); );
const loginResponse = await this.authService.logIn(credentials); const loginResponse = await this.loginStrategyService.logIn(credentials);
if (this.handleCaptchaRequired(loginResponse)) { if (this.handleCaptchaRequired(loginResponse)) {
return { captchaRequired: true }; return { captchaRequired: true };
} }

View File

@@ -4,8 +4,8 @@ import { ActivatedRoute, Router } from "@angular/router";
import { MockProxy, mock } from "jest-mock-extended"; import { MockProxy, mock } from "jest-mock-extended";
import { Observable, of } from "rxjs"; import { Observable, of } from "rxjs";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
@@ -46,7 +46,7 @@ describe("SsoComponent", () => {
let fixture: ComponentFixture<TestSsoComponent>; let fixture: ComponentFixture<TestSsoComponent>;
// Mock Services // Mock Services
let mockAuthService: MockProxy<AuthService>; let mockLoginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
let mockRouter: MockProxy<Router>; let mockRouter: MockProxy<Router>;
let mockI18nService: MockProxy<I18nService>; let mockI18nService: MockProxy<I18nService>;
@@ -88,7 +88,7 @@ describe("SsoComponent", () => {
beforeEach(() => { beforeEach(() => {
// Mock Services // Mock Services
mockAuthService = mock<AuthService>(); mockLoginStrategyService = mock<LoginStrategyServiceAbstraction>();
mockRouter = mock<Router>(); mockRouter = mock<Router>();
mockI18nService = mock<I18nService>(); mockI18nService = mock<I18nService>();
@@ -108,7 +108,7 @@ describe("SsoComponent", () => {
mockLogService = mock<LogService>(); mockLogService = mock<LogService>();
mockConfigService = mock<ConfigServiceAbstraction>(); mockConfigService = mock<ConfigServiceAbstraction>();
// Mock authService.logIn params // Mock loginStrategyService.logIn params
code = "code"; code = "code";
codeVerifier = "codeVerifier"; codeVerifier = "codeVerifier";
orgIdFromState = "orgIdFromState"; orgIdFromState = "orgIdFromState";
@@ -167,7 +167,7 @@ describe("SsoComponent", () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [TestSsoComponent], declarations: [TestSsoComponent],
providers: [ providers: [
{ provide: AuthService, useValue: mockAuthService }, { provide: LoginStrategyServiceAbstraction, useValue: mockLoginStrategyService },
{ provide: Router, useValue: mockRouter }, { provide: Router, useValue: mockRouter },
{ provide: I18nService, useValue: mockI18nService }, { provide: I18nService, useValue: mockI18nService },
{ provide: ActivatedRoute, useValue: mockActivatedRoute }, { provide: ActivatedRoute, useValue: mockActivatedRoute },
@@ -230,12 +230,12 @@ describe("SsoComponent", () => {
mockAcctDecryptionOpts.withMasterPassword, mockAcctDecryptionOpts.withMasterPassword,
); );
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
it("calls authService.logIn and navigates to the component's defined 2FA route when the auth result requires 2FA and onSuccessfulLoginTwoFactorNavigate is not defined", async () => { it("calls authService.logIn and navigates to the component's defined 2FA route when the auth result requires 2FA and onSuccessfulLoginTwoFactorNavigate is not defined", async () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginTwoFactorNavigate).not.toHaveBeenCalled(); expect(mockOnSuccessfulLoginTwoFactorNavigate).not.toHaveBeenCalled();
@@ -256,7 +256,7 @@ describe("SsoComponent", () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginTwoFactorNavigate).toHaveBeenCalledTimes(1); expect(mockOnSuccessfulLoginTwoFactorNavigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).not.toHaveBeenCalled(); expect(mockRouter.navigate).not.toHaveBeenCalled();
expect(mockLogService.error).not.toHaveBeenCalled(); expect(mockLogService.error).not.toHaveBeenCalled();
@@ -267,7 +267,7 @@ describe("SsoComponent", () => {
const testChangePasswordOnSuccessfulLogin = () => { const testChangePasswordOnSuccessfulLogin = () => {
it("navigates to the component's defined change password route when onSuccessfulLoginChangePasswordNavigate callback is undefined", async () => { it("navigates to the component's defined change password route when onSuccessfulLoginChangePasswordNavigate callback is undefined", async () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginChangePasswordNavigate).not.toHaveBeenCalled(); expect(mockOnSuccessfulLoginChangePasswordNavigate).not.toHaveBeenCalled();
@@ -290,7 +290,7 @@ describe("SsoComponent", () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginChangePasswordNavigate).toHaveBeenCalledTimes(1); expect(mockOnSuccessfulLoginChangePasswordNavigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).not.toHaveBeenCalled(); expect(mockRouter.navigate).not.toHaveBeenCalled();
expect(mockLogService.error).not.toHaveBeenCalled(); expect(mockLogService.error).not.toHaveBeenCalled();
@@ -301,7 +301,7 @@ describe("SsoComponent", () => {
it(`navigates to the component's defined forcePasswordResetRoute when response.forcePasswordReset is ${reasonString}`, async () => { it(`navigates to the component's defined forcePasswordResetRoute when response.forcePasswordReset is ${reasonString}`, async () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginForceResetNavigate).not.toHaveBeenCalled(); expect(mockOnSuccessfulLoginForceResetNavigate).not.toHaveBeenCalled();
@@ -322,7 +322,7 @@ describe("SsoComponent", () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginForceResetNavigate).toHaveBeenCalledTimes(1); expect(mockOnSuccessfulLoginForceResetNavigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).not.toHaveBeenCalled(); expect(mockRouter.navigate).not.toHaveBeenCalled();
expect(mockLogService.error).not.toHaveBeenCalled(); expect(mockLogService.error).not.toHaveBeenCalled();
@@ -342,12 +342,12 @@ describe("SsoComponent", () => {
); );
authResult = new AuthResult(); authResult = new AuthResult();
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
it("navigates to the component's defined trustedDeviceEncRoute route and sets correct flag when onSuccessfulLoginTdeNavigate is undefined ", async () => { it("navigates to the component's defined trustedDeviceEncRoute route and sets correct flag when onSuccessfulLoginTdeNavigate is undefined ", async () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockStateService.setForceSetPasswordReason).toHaveBeenCalledWith( expect(mockStateService.setForceSetPasswordReason).toHaveBeenCalledWith(
ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission, ForceSetPasswordReason.TdeUserWithoutPasswordHasPasswordResetPermission,
@@ -379,7 +379,7 @@ describe("SsoComponent", () => {
authResult = new AuthResult(); authResult = new AuthResult();
authResult.forcePasswordReset = ForceSetPasswordReason.AdminForcePasswordReset; authResult.forcePasswordReset = ForceSetPasswordReason.AdminForcePasswordReset;
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
testForceResetOnSuccessfulLogin(reasonString); testForceResetOnSuccessfulLogin(reasonString);
@@ -396,13 +396,13 @@ describe("SsoComponent", () => {
authResult = new AuthResult(); authResult = new AuthResult();
authResult.forcePasswordReset = ForceSetPasswordReason.None; authResult.forcePasswordReset = ForceSetPasswordReason.None;
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
it("navigates to the component's defined trusted device encryption route when login is successful and no callback is defined", async () => { it("navigates to the component's defined trusted device encryption route when login is successful and no callback is defined", async () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).toHaveBeenCalledTimes(1); expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
expect(mockRouter.navigate).toHaveBeenCalledWith( expect(mockRouter.navigate).toHaveBeenCalledWith(
[_component.trustedDeviceEncRoute], [_component.trustedDeviceEncRoute],
@@ -417,7 +417,7 @@ describe("SsoComponent", () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginTdeNavigate).toHaveBeenCalledTimes(1); expect(mockOnSuccessfulLoginTdeNavigate).toHaveBeenCalledTimes(1);
@@ -430,7 +430,7 @@ describe("SsoComponent", () => {
describe("Set Master Password scenarios", () => { describe("Set Master Password scenarios", () => {
beforeEach(() => { beforeEach(() => {
const authResult = new AuthResult(); const authResult = new AuthResult();
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
describe("Given user needs to set a master password", () => { describe("Given user needs to set a master password", () => {
@@ -451,7 +451,7 @@ describe("SsoComponent", () => {
); );
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalledTimes(1); expect(mockLoginStrategyService.logIn).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginChangePasswordNavigate).not.toHaveBeenCalled(); expect(mockOnSuccessfulLoginChangePasswordNavigate).not.toHaveBeenCalled();
expect(mockRouter.navigate).not.toHaveBeenCalledWith([_component.changePasswordRoute], { expect(mockRouter.navigate).not.toHaveBeenCalledWith([_component.changePasswordRoute], {
@@ -477,7 +477,7 @@ describe("SsoComponent", () => {
const authResult = new AuthResult(); const authResult = new AuthResult();
authResult.forcePasswordReset = forceResetPasswordReason; authResult.forcePasswordReset = forceResetPasswordReason;
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
testForceResetOnSuccessfulLogin(reasonString); testForceResetOnSuccessfulLogin(reasonString);
@@ -494,13 +494,13 @@ describe("SsoComponent", () => {
mockAcctDecryptionOpts.withMasterPassword, mockAcctDecryptionOpts.withMasterPassword,
); );
authResult.forcePasswordReset = ForceSetPasswordReason.None; authResult.forcePasswordReset = ForceSetPasswordReason.None;
mockAuthService.logIn.mockResolvedValue(authResult); mockLoginStrategyService.logIn.mockResolvedValue(authResult);
}); });
it("calls authService.logIn and navigates to the component's defined success route when the login is successful", async () => { it("calls authService.logIn and navigates to the component's defined success route when the login is successful", async () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalled(); expect(mockLoginStrategyService.logIn).toHaveBeenCalled();
expect(mockOnSuccessfulLoginNavigate).not.toHaveBeenCalled(); expect(mockOnSuccessfulLoginNavigate).not.toHaveBeenCalled();
expect(mockOnSuccessfulLogin).not.toHaveBeenCalled(); expect(mockOnSuccessfulLogin).not.toHaveBeenCalled();
@@ -516,7 +516,7 @@ describe("SsoComponent", () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalled(); expect(mockLoginStrategyService.logIn).toHaveBeenCalled();
expect(mockOnSuccessfulLogin).toHaveBeenCalledTimes(1); expect(mockOnSuccessfulLogin).toHaveBeenCalledTimes(1);
expect(mockOnSuccessfulLoginNavigate).not.toHaveBeenCalled(); expect(mockOnSuccessfulLoginNavigate).not.toHaveBeenCalled();
@@ -533,7 +533,7 @@ describe("SsoComponent", () => {
await _component.logIn(code, codeVerifier, orgIdFromState); await _component.logIn(code, codeVerifier, orgIdFromState);
expect(mockAuthService.logIn).toHaveBeenCalled(); expect(mockLoginStrategyService.logIn).toHaveBeenCalled();
expect(mockOnSuccessfulLoginNavigate).toHaveBeenCalledTimes(1); expect(mockOnSuccessfulLoginNavigate).toHaveBeenCalledTimes(1);
@@ -547,7 +547,7 @@ describe("SsoComponent", () => {
it("calls handleLoginError when an error is thrown during logIn", async () => { it("calls handleLoginError when an error is thrown during logIn", async () => {
const errorMessage = "Key Connector error"; const errorMessage = "Key Connector error";
const error = new Error(errorMessage); const error = new Error(errorMessage);
mockAuthService.logIn.mockRejectedValue(error); mockLoginStrategyService.logIn.mockRejectedValue(error);
const handleLoginErrorSpy = jest.spyOn(_component, "handleLoginError"); const handleLoginErrorSpy = jest.spyOn(_component, "handleLoginError");

View File

@@ -2,11 +2,10 @@ import { Directive } from "@angular/core";
import { ActivatedRoute, NavigationExtras, Router } from "@angular/router"; import { ActivatedRoute, NavigationExtras, Router } from "@angular/router";
import { first } from "rxjs/operators"; import { first } from "rxjs/operators";
import { LoginStrategyServiceAbstraction, SsoLoginCredentials } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
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 { SsoLoginCredentials } from "@bitwarden/common/auth/models/domain/login-credentials";
import { TrustedDeviceUserDecryptionOption } from "@bitwarden/common/auth/models/domain/user-decryption-options/trusted-device-user-decryption-option"; import { TrustedDeviceUserDecryptionOption } from "@bitwarden/common/auth/models/domain/user-decryption-options/trusted-device-user-decryption-option";
import { SsoPreValidateResponse } from "@bitwarden/common/auth/models/response/sso-pre-validate.response"; import { SsoPreValidateResponse } from "@bitwarden/common/auth/models/response/sso-pre-validate.response";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction"; import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
@@ -47,7 +46,7 @@ export class SsoComponent {
protected codeChallenge: string; protected codeChallenge: string;
constructor( constructor(
protected authService: AuthService, protected loginStrategyService: LoginStrategyServiceAbstraction,
protected router: Router, protected router: Router,
protected i18nService: I18nService, protected i18nService: I18nService,
protected route: ActivatedRoute, protected route: ActivatedRoute,
@@ -187,7 +186,7 @@ export class SsoComponent {
this.redirectUri, this.redirectUri,
orgSsoIdentifier, orgSsoIdentifier,
); );
this.formPromise = this.authService.logIn(credentials); this.formPromise = this.loginStrategyService.logIn(credentials);
const authResult = await this.formPromise; const authResult = await this.formPromise;
const acctDecryptionOpts: AccountDecryptionOptions = const acctDecryptionOpts: AccountDecryptionOptions =

View File

@@ -5,8 +5,8 @@ import { MockProxy, mock } from "jest-mock-extended";
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
@@ -43,7 +43,7 @@ describe("TwoFactorComponent", () => {
let fixture: ComponentFixture<TestTwoFactorComponent>; let fixture: ComponentFixture<TestTwoFactorComponent>;
// Mock Services // Mock Services
let mockAuthService: MockProxy<AuthService>; let mockLoginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
let mockRouter: MockProxy<Router>; let mockRouter: MockProxy<Router>;
let mockI18nService: MockProxy<I18nService>; let mockI18nService: MockProxy<I18nService>;
let mockApiService: MockProxy<ApiService>; let mockApiService: MockProxy<ApiService>;
@@ -69,7 +69,7 @@ describe("TwoFactorComponent", () => {
}; };
beforeEach(() => { beforeEach(() => {
mockAuthService = mock<AuthService>(); mockLoginStrategyService = mock<LoginStrategyServiceAbstraction>();
mockRouter = mock<Router>(); mockRouter = mock<Router>();
mockI18nService = mock<I18nService>(); mockI18nService = mock<I18nService>();
mockApiService = mock<ApiService>(); mockApiService = mock<ApiService>();
@@ -129,7 +129,7 @@ describe("TwoFactorComponent", () => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [TestTwoFactorComponent], declarations: [TestTwoFactorComponent],
providers: [ providers: [
{ provide: AuthService, useValue: mockAuthService }, { provide: LoginStrategyServiceAbstraction, useValue: mockLoginStrategyService },
{ provide: Router, useValue: mockRouter }, { provide: Router, useValue: mockRouter },
{ provide: I18nService, useValue: mockI18nService }, { provide: I18nService, useValue: mockI18nService },
{ provide: ApiService, useValue: mockApiService }, { provide: ApiService, useValue: mockApiService },
@@ -216,13 +216,13 @@ describe("TwoFactorComponent", () => {
it("calls authService.logInTwoFactor with correct parameters when form is submitted", async () => { it("calls authService.logInTwoFactor with correct parameters when form is submitted", async () => {
// Arrange // Arrange
mockAuthService.logInTwoFactor.mockResolvedValue(new AuthResult()); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
// Act // Act
await component.doSubmit(); await component.doSubmit();
// Assert // Assert
expect(mockAuthService.logInTwoFactor).toHaveBeenCalledWith( expect(mockLoginStrategyService.logInTwoFactor).toHaveBeenCalledWith(
new TokenTwoFactorRequest(component.selectedProviderType, token, remember), new TokenTwoFactorRequest(component.selectedProviderType, token, remember),
captchaToken, captchaToken,
); );
@@ -234,7 +234,7 @@ describe("TwoFactorComponent", () => {
const authResult = new AuthResult(); const authResult = new AuthResult();
authResult.captchaSiteKey = captchaSiteKey; authResult.captchaSiteKey = captchaSiteKey;
mockAuthService.logInTwoFactor.mockResolvedValue(authResult); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
// Note: the any casts are required b/c typescript cant recognize that // Note: the any casts are required b/c typescript cant recognize that
// handleCaptureRequired is a method on TwoFactorComponent b/c it is inherited // handleCaptureRequired is a method on TwoFactorComponent b/c it is inherited
@@ -254,7 +254,7 @@ describe("TwoFactorComponent", () => {
it("calls onSuccessfulLogin when defined", async () => { it("calls onSuccessfulLogin when defined", async () => {
// Arrange // Arrange
component.onSuccessfulLogin = jest.fn().mockResolvedValue(undefined); component.onSuccessfulLogin = jest.fn().mockResolvedValue(undefined);
mockAuthService.logInTwoFactor.mockResolvedValue(new AuthResult()); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
// Act // Act
await component.doSubmit(); await component.doSubmit();
@@ -265,7 +265,7 @@ describe("TwoFactorComponent", () => {
it("calls loginService.clearValues() when login is successful", async () => { it("calls loginService.clearValues() when login is successful", async () => {
// Arrange // Arrange
mockAuthService.logInTwoFactor.mockResolvedValue(new AuthResult()); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
// spy on loginService.clearValues // spy on loginService.clearValues
const clearValuesSpy = jest.spyOn(mockLoginService, "clearValues"); const clearValuesSpy = jest.spyOn(mockLoginService, "clearValues");
@@ -279,7 +279,7 @@ describe("TwoFactorComponent", () => {
describe("Set Master Password scenarios", () => { describe("Set Master Password scenarios", () => {
beforeEach(() => { beforeEach(() => {
const authResult = new AuthResult(); const authResult = new AuthResult();
mockAuthService.logInTwoFactor.mockResolvedValue(authResult); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
}); });
describe("Given user needs to set a master password", () => { describe("Given user needs to set a master password", () => {
@@ -323,7 +323,7 @@ describe("TwoFactorComponent", () => {
const authResult = new AuthResult(); const authResult = new AuthResult();
authResult.forcePasswordReset = forceResetPasswordReason; authResult.forcePasswordReset = forceResetPasswordReason;
mockAuthService.logInTwoFactor.mockResolvedValue(authResult); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
}); });
testForceResetOnSuccessfulLogin(reasonString); testForceResetOnSuccessfulLogin(reasonString);
@@ -333,7 +333,7 @@ describe("TwoFactorComponent", () => {
it("calls onSuccessfulLoginNavigate when the callback is defined", async () => { it("calls onSuccessfulLoginNavigate when the callback is defined", async () => {
// Arrange // Arrange
component.onSuccessfulLoginNavigate = jest.fn().mockResolvedValue(undefined); component.onSuccessfulLoginNavigate = jest.fn().mockResolvedValue(undefined);
mockAuthService.logInTwoFactor.mockResolvedValue(new AuthResult()); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
// Act // Act
await component.doSubmit(); await component.doSubmit();
@@ -343,7 +343,7 @@ describe("TwoFactorComponent", () => {
}); });
it("navigates to the component's defined success route when the login is successful and onSuccessfulLoginNavigate is undefined", async () => { it("navigates to the component's defined success route when the login is successful and onSuccessfulLoginNavigate is undefined", async () => {
mockAuthService.logInTwoFactor.mockResolvedValue(new AuthResult()); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(new AuthResult());
// Act // Act
await component.doSubmit(); await component.doSubmit();
@@ -386,7 +386,7 @@ describe("TwoFactorComponent", () => {
); );
const authResult = new AuthResult(); const authResult = new AuthResult();
mockAuthService.logInTwoFactor.mockResolvedValue(authResult); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
}); });
it("navigates to the component's defined trusted device encryption route and sets correct flag when user doesn't have a MP and key connector isn't enabled", async () => { it("navigates to the component's defined trusted device encryption route and sets correct flag when user doesn't have a MP and key connector isn't enabled", async () => {
@@ -422,7 +422,7 @@ describe("TwoFactorComponent", () => {
const authResult = new AuthResult(); const authResult = new AuthResult();
authResult.forcePasswordReset = forceResetPasswordReason; authResult.forcePasswordReset = forceResetPasswordReason;
mockAuthService.logInTwoFactor.mockResolvedValue(authResult); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
}); });
testForceResetOnSuccessfulLogin(reasonString); testForceResetOnSuccessfulLogin(reasonString);
@@ -438,7 +438,7 @@ describe("TwoFactorComponent", () => {
authResult = new AuthResult(); authResult = new AuthResult();
authResult.forcePasswordReset = ForceSetPasswordReason.None; authResult.forcePasswordReset = ForceSetPasswordReason.None;
mockAuthService.logInTwoFactor.mockResolvedValue(authResult); mockLoginStrategyService.logInTwoFactor.mockResolvedValue(authResult);
}); });
it("navigates to the component's defined trusted device encryption route when login is successful and onSuccessfulLoginTdeNavigate is undefined", async () => { it("navigates to the component's defined trusted device encryption route when login is successful and onSuccessfulLoginTdeNavigate is undefined", async () => {

View File

@@ -5,8 +5,8 @@ import { first } from "rxjs/operators";
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { WINDOW } from "@bitwarden/angular/services/injection-tokens"; import { WINDOW } from "@bitwarden/angular/services/injection-tokens";
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { LoginService } from "@bitwarden/common/auth/abstractions/login.service"; import { LoginService } from "@bitwarden/common/auth/abstractions/login.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
@@ -70,7 +70,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
} }
constructor( constructor(
protected authService: AuthService, protected loginStrategyService: LoginStrategyServiceAbstraction,
protected router: Router, protected router: Router,
protected i18nService: I18nService, protected i18nService: I18nService,
protected apiService: ApiService, protected apiService: ApiService,
@@ -243,7 +243,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
} }
async doSubmit() { async doSubmit() {
this.formPromise = this.authService.logInTwoFactor( this.formPromise = this.loginStrategyService.logInTwoFactor(
new TokenTwoFactorRequest(this.selectedProviderType, this.token, this.remember), new TokenTwoFactorRequest(this.selectedProviderType, this.token, this.remember),
this.captchaToken, this.captchaToken,
); );
@@ -424,7 +424,7 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
return; return;
} }
if (this.authService.email == null) { if (this.loginStrategyService.email == null) {
this.platformUtilsService.showToast( this.platformUtilsService.showToast(
"error", "error",
this.i18nService.t("errorOccurred"), this.i18nService.t("errorOccurred"),
@@ -435,12 +435,12 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
try { try {
const request = new TwoFactorEmailRequest(); const request = new TwoFactorEmailRequest();
request.email = this.authService.email; request.email = this.loginStrategyService.email;
request.masterPasswordHash = this.authService.masterPasswordHash; request.masterPasswordHash = this.loginStrategyService.masterPasswordHash;
request.ssoEmail2FaSessionToken = this.authService.ssoEmail2FaSessionToken; request.ssoEmail2FaSessionToken = this.loginStrategyService.ssoEmail2FaSessionToken;
request.deviceIdentifier = await this.appIdService.getAppId(); request.deviceIdentifier = await this.appIdService.getAppId();
request.authRequestAccessCode = this.authService.accessCode; request.authRequestAccessCode = this.loginStrategyService.accessCode;
request.authRequestId = this.authService.authRequestId; request.authRequestId = this.loginStrategyService.authRequestId;
this.emailPromise = this.apiService.postTwoFactorEmail(request); this.emailPromise = this.apiService.postTwoFactorEmail(request);
await this.emailPromise; await this.emailPromise;
if (doToast) { if (doToast) {
@@ -476,15 +476,18 @@ export class TwoFactorComponent extends CaptchaProtectedComponent implements OnI
get authing(): boolean { get authing(): boolean {
return ( return (
this.authService.authingWithPassword() || this.loginStrategyService.authingWithPassword() ||
this.authService.authingWithSso() || this.loginStrategyService.authingWithSso() ||
this.authService.authingWithUserApiKey() || this.loginStrategyService.authingWithUserApiKey() ||
this.authService.authingWithPasswordless() this.loginStrategyService.authingWithPasswordless()
); );
} }
get needsLock(): boolean { get needsLock(): boolean {
return this.authService.authingWithSso() || this.authService.authingWithUserApiKey(); return (
this.loginStrategyService.authingWithSso() ||
this.loginStrategyService.authingWithUserApiKey()
);
} }
launchDuoFrameless() { launchDuoFrameless() {

View File

@@ -1,6 +1,11 @@
import { LOCALE_ID, NgModule } from "@angular/core"; import { LOCALE_ID, NgModule } from "@angular/core";
import { PinCryptoServiceAbstraction, PinCryptoService } from "@bitwarden/auth/common"; import {
PinCryptoServiceAbstraction,
PinCryptoService,
LoginStrategyServiceAbstraction,
LoginStrategyService,
} from "@bitwarden/auth/common";
import { AvatarUpdateService as AccountUpdateServiceAbstraction } from "@bitwarden/common/abstractions/account/avatar-update.service"; import { AvatarUpdateService as AccountUpdateServiceAbstraction } 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";
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service"; import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
@@ -274,6 +279,16 @@ import { ModalService } from "./modal.service";
{ {
provide: AuthServiceAbstraction, provide: AuthServiceAbstraction,
useClass: AuthService, useClass: AuthService,
deps: [
MessagingServiceAbstraction,
CryptoServiceAbstraction,
ApiServiceAbstraction,
StateServiceAbstraction,
],
},
{
provide: LoginStrategyServiceAbstraction,
useClass: LoginStrategyService,
deps: [ deps: [
CryptoServiceAbstraction, CryptoServiceAbstraction,
ApiServiceAbstraction, ApiServiceAbstraction,
@@ -747,7 +762,7 @@ import { ModalService } from "./modal.service";
{ {
provide: AnonymousHubServiceAbstraction, provide: AnonymousHubServiceAbstraction,
useClass: AnonymousHubService, useClass: AnonymousHubService,
deps: [EnvironmentServiceAbstraction, AuthServiceAbstraction, LogService], deps: [EnvironmentServiceAbstraction, LoginStrategyServiceAbstraction, LogService],
}, },
{ {
provide: ValidationServiceAbstraction, provide: ValidationServiceAbstraction,
@@ -828,7 +843,7 @@ import { ModalService } from "./modal.service";
useClass: WebAuthnLoginService, useClass: WebAuthnLoginService,
deps: [ deps: [
WebAuthnLoginApiServiceAbstraction, WebAuthnLoginApiServiceAbstraction,
AuthServiceAbstraction, LoginStrategyServiceAbstraction,
ConfigServiceAbstraction, ConfigServiceAbstraction,
WebAuthnLoginPrfCryptoServiceAbstraction, WebAuthnLoginPrfCryptoServiceAbstraction,
WINDOW, WINDOW,

View File

@@ -1 +1,2 @@
export * from "./pin-crypto.service.abstraction"; export * from "./pin-crypto.service.abstraction";
export * from "./login-strategy.service";

View File

@@ -0,0 +1,48 @@
import { Observable } from "rxjs";
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 { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
import { MasterKey } from "@bitwarden/common/types/key";
import {
UserApiLoginCredentials,
PasswordLoginCredentials,
SsoLoginCredentials,
AuthRequestLoginCredentials,
WebAuthnLoginCredentials,
} from "../models/domain/login-credentials";
export abstract class LoginStrategyServiceAbstraction {
masterPasswordHash: string;
email: string;
accessCode: string;
authRequestId: string;
ssoEmail2FaSessionToken: string;
logIn: (
credentials:
| UserApiLoginCredentials
| PasswordLoginCredentials
| SsoLoginCredentials
| AuthRequestLoginCredentials
| WebAuthnLoginCredentials,
) => Promise<AuthResult>;
logInTwoFactor: (
twoFactor: TokenTwoFactorRequest,
captchaResponse: string,
) => Promise<AuthResult>;
makePreloginKey: (masterPassword: string, email: string) => Promise<MasterKey>;
authingWithUserApiKey: () => boolean;
authingWithSso: () => boolean;
authingWithPassword: () => boolean;
authingWithPasswordless: () => boolean;
authResponsePushNotification: (notification: AuthRequestPushNotification) => Promise<any>;
passwordlessLogin: (
id: string,
key: string,
requestApproved: boolean,
) => Promise<AuthRequestResponse>;
getPushNotificationObs$: () => Observable<any>;
}

View File

@@ -1,21 +1,22 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { LogService } from "../../platform/abstractions/log.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { StateService } from "../../platform/abstractions/state.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { Utils } from "../../platform/misc/utils"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { CsprngArray } from "../../types/csprng"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { MasterKey, UserKey } from "../../types/key"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { DeviceTrustCryptoServiceAbstraction } from "../abstractions/device-trust-crypto.service.abstraction"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { TokenService } from "../abstractions/token.service"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { CsprngArray } from "@bitwarden/common/types/csprng";
import { MasterKey, UserKey } from "@bitwarden/common/types/key";
import { AuthRequestLoginCredentials } from "../models/domain/login-credentials"; import { AuthRequestLoginCredentials } from "../models/domain/login-credentials";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { AuthRequestLoginStrategy } from "./auth-request-login.strategy"; import { AuthRequestLoginStrategy } from "./auth-request-login.strategy";
import { identityTokenResponseFactory } from "./login.strategy.spec"; import { identityTokenResponseFactory } from "./login.strategy.spec";

View File

@@ -1,18 +1,19 @@
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { LogService } from "../../platform/abstractions/log.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { PasswordTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/password-token.request";
import { StateService } from "../../platform/abstractions/state.service"; import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
import { DeviceTrustCryptoServiceAbstraction } from "../abstractions/device-trust-crypto.service.abstraction"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { TokenService } from "../abstractions/token.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { AuthResult } from "../models/domain/auth-result"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { AuthRequestLoginCredentials } from "../models/domain/login-credentials"; import { AuthRequestLoginCredentials } from "../models/domain/login-credentials";
import { PasswordTokenRequest } from "../models/request/identity-token/password-token.request";
import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { LoginStrategy } from "./login.strategy"; import { LoginStrategy } from "./login.strategy";

View File

@@ -1,43 +1,44 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { LogService } from "../../platform/abstractions/log.service"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { StateService } from "../../platform/abstractions/state.service"; import { PasswordTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/password-token.request";
import { Utils } from "../../platform/misc/utils"; import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
import { IdentityCaptchaResponse } from "@bitwarden/common/auth/models/response/identity-captcha.response";
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
import { MasterPasswordPolicyResponse } from "@bitwarden/common/auth/models/response/master-password-policy.response";
import { IUserDecryptionOptionsServerResponse } from "@bitwarden/common/auth/models/response/user-decryption-options/user-decryption-options.response";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { import {
Account, Account,
AccountDecryptionOptions,
AccountKeys,
AccountProfile, AccountProfile,
AccountTokens, AccountTokens,
} from "../../platform/models/domain/account"; AccountKeys,
import { EncString } from "../../platform/models/domain/enc-string"; AccountDecryptionOptions,
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; } from "@bitwarden/common/platform/models/domain/account";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { import {
PasswordStrengthService,
PasswordStrengthServiceAbstraction, PasswordStrengthServiceAbstraction,
} from "../../tools/password-strength"; PasswordStrengthService,
import { CsprngArray } from "../../types/csprng"; } from "@bitwarden/common/tools/password-strength";
import { UserKey, MasterKey, DeviceKey } from "../../types/key"; import { CsprngArray } from "@bitwarden/common/types/csprng";
import { AuthService } from "../abstractions/auth.service"; import { UserKey, MasterKey, DeviceKey } from "@bitwarden/common/types/key";
import { TokenService } from "../abstractions/token.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { LoginStrategyServiceAbstraction } from "../abstractions/login-strategy.service";
import { TwoFactorProviderType } from "../enums/two-factor-provider-type";
import { AuthResult } from "../models/domain/auth-result";
import { ForceSetPasswordReason } from "../models/domain/force-set-password-reason";
import { PasswordLoginCredentials } from "../models/domain/login-credentials"; import { PasswordLoginCredentials } from "../models/domain/login-credentials";
import { PasswordTokenRequest } from "../models/request/identity-token/password-token.request";
import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request";
import { IdentityCaptchaResponse } from "../models/response/identity-captcha.response";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "../models/response/identity-two-factor.response";
import { MasterPasswordPolicyResponse } from "../models/response/master-password-policy.response";
import { IUserDecryptionOptionsServerResponse } from "../models/response/user-decryption-options/user-decryption-options.response";
import { PasswordLoginStrategy } from "./password-login.strategy"; import { PasswordLoginStrategy } from "./password-login.strategy";
@@ -93,6 +94,7 @@ export function identityTokenResponseFactory(
// TODO: add tests for latest changes to base class for TDE // TODO: add tests for latest changes to base class for TDE
describe("LoginStrategy", () => { describe("LoginStrategy", () => {
let loginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
let cryptoService: MockProxy<CryptoService>; let cryptoService: MockProxy<CryptoService>;
let apiService: MockProxy<ApiService>; let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>; let tokenService: MockProxy<TokenService>;
@@ -102,7 +104,6 @@ describe("LoginStrategy", () => {
let logService: MockProxy<LogService>; let logService: MockProxy<LogService>;
let stateService: MockProxy<StateService>; let stateService: MockProxy<StateService>;
let twoFactorService: MockProxy<TwoFactorService>; let twoFactorService: MockProxy<TwoFactorService>;
let authService: MockProxy<AuthService>;
let policyService: MockProxy<PolicyService>; let policyService: MockProxy<PolicyService>;
let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>; let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>;
@@ -110,6 +111,7 @@ describe("LoginStrategy", () => {
let credentials: PasswordLoginCredentials; let credentials: PasswordLoginCredentials;
beforeEach(async () => { beforeEach(async () => {
loginStrategyService = mock<LoginStrategyServiceAbstraction>();
cryptoService = mock<CryptoService>(); cryptoService = mock<CryptoService>();
apiService = mock<ApiService>(); apiService = mock<ApiService>();
tokenService = mock<TokenService>(); tokenService = mock<TokenService>();
@@ -119,7 +121,6 @@ describe("LoginStrategy", () => {
logService = mock<LogService>(); logService = mock<LogService>();
stateService = mock<StateService>(); stateService = mock<StateService>();
twoFactorService = mock<TwoFactorService>(); twoFactorService = mock<TwoFactorService>();
authService = mock<AuthService>();
policyService = mock<PolicyService>(); policyService = mock<PolicyService>();
passwordStrengthService = mock<PasswordStrengthService>(); passwordStrengthService = mock<PasswordStrengthService>();
@@ -139,7 +140,7 @@ describe("LoginStrategy", () => {
twoFactorService, twoFactorService,
passwordStrengthService, passwordStrengthService,
policyService, policyService,
authService, loginStrategyService,
); );
credentials = new PasswordLoginCredentials(email, masterPassword); credentials = new PasswordLoginCredentials(email, masterPassword);
}); });

View File

@@ -1,40 +1,41 @@
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { ClientType } from "../../enums"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { KeysRequest } from "../../models/request/keys.request"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { LogService } from "../../platform/abstractions/log.service"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { DeviceRequest } from "@bitwarden/common/auth/models/request/identity-token/device.request";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { PasswordTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/password-token.request";
import { StateService } from "../../platform/abstractions/state.service"; import { SsoTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/sso-token.request";
import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
import { UserApiTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/user-api-token.request";
import { WebAuthnLoginTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/webauthn-login-token.request";
import { IdentityCaptchaResponse } from "@bitwarden/common/auth/models/response/identity-captcha.response";
import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
import { ClientType } from "@bitwarden/common/enums";
import { KeysRequest } from "@bitwarden/common/models/request/keys.request";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { import {
Account,
AccountDecryptionOptions,
AccountKeys, AccountKeys,
Account,
AccountProfile, AccountProfile,
AccountTokens, AccountTokens,
} from "../../platform/models/domain/account"; AccountDecryptionOptions,
import { TokenService } from "../abstractions/token.service"; } from "@bitwarden/common/platform/models/domain/account";
import { TwoFactorService } from "../abstractions/two-factor.service";
import { TwoFactorProviderType } from "../enums/two-factor-provider-type";
import { AuthResult } from "../models/domain/auth-result";
import { ForceSetPasswordReason } from "../models/domain/force-set-password-reason";
import { import {
AuthRequestLoginCredentials, UserApiLoginCredentials,
PasswordLoginCredentials, PasswordLoginCredentials,
SsoLoginCredentials, SsoLoginCredentials,
UserApiLoginCredentials, AuthRequestLoginCredentials,
WebAuthnLoginCredentials, WebAuthnLoginCredentials,
} from "../models/domain/login-credentials"; } from "../models/domain/login-credentials";
import { DeviceRequest } from "../models/request/identity-token/device.request";
import { PasswordTokenRequest } from "../models/request/identity-token/password-token.request";
import { SsoTokenRequest } from "../models/request/identity-token/sso-token.request";
import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request";
import { UserApiTokenRequest } from "../models/request/identity-token/user-api-token.request";
import { WebAuthnLoginTokenRequest } from "../models/request/identity-token/webauthn-login-token.request";
import { IdentityCaptchaResponse } from "../models/response/identity-captcha.response";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "../models/response/identity-two-factor.response";
type IdentityResponse = IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse; type IdentityResponse = IdentityTokenResponse | IdentityTwoFactorResponse | IdentityCaptchaResponse;

View File

@@ -1,31 +1,32 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { LogService } from "../../platform/abstractions/log.service"; import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { StateService } from "../../platform/abstractions/state.service"; import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
import { HashPurpose } from "../../platform/enums"; import { MasterPasswordPolicyResponse } from "@bitwarden/common/auth/models/response/master-password-policy.response";
import { Utils } from "../../platform/misc/utils"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { HashPurpose } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { import {
PasswordStrengthService,
PasswordStrengthServiceAbstraction, PasswordStrengthServiceAbstraction,
} from "../../tools/password-strength"; PasswordStrengthService,
import { CsprngArray } from "../../types/csprng"; } from "@bitwarden/common/tools/password-strength";
import { MasterKey, UserKey } from "../../types/key"; import { CsprngArray } from "@bitwarden/common/types/csprng";
import { AuthService } from "../abstractions/auth.service"; import { MasterKey, UserKey } from "@bitwarden/common/types/key";
import { TokenService } from "../abstractions/token.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { LoginStrategyServiceAbstraction } from "../abstractions";
import { TwoFactorProviderType } from "../enums/two-factor-provider-type";
import { ForceSetPasswordReason } from "../models/domain/force-set-password-reason";
import { PasswordLoginCredentials } from "../models/domain/login-credentials"; import { PasswordLoginCredentials } from "../models/domain/login-credentials";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "../models/response/identity-two-factor.response";
import { MasterPasswordPolicyResponse } from "../models/response/master-password-policy.response";
import { identityTokenResponseFactory } from "./login.strategy.spec"; import { identityTokenResponseFactory } from "./login.strategy.spec";
import { PasswordLoginStrategy } from "./password-login.strategy"; import { PasswordLoginStrategy } from "./password-login.strategy";
@@ -46,6 +47,7 @@ const masterPasswordPolicy = new MasterPasswordPolicyResponse({
}); });
describe("PasswordLoginStrategy", () => { describe("PasswordLoginStrategy", () => {
let loginStrategyService: MockProxy<LoginStrategyServiceAbstraction>;
let cryptoService: MockProxy<CryptoService>; let cryptoService: MockProxy<CryptoService>;
let apiService: MockProxy<ApiService>; let apiService: MockProxy<ApiService>;
let tokenService: MockProxy<TokenService>; let tokenService: MockProxy<TokenService>;
@@ -55,7 +57,6 @@ describe("PasswordLoginStrategy", () => {
let logService: MockProxy<LogService>; let logService: MockProxy<LogService>;
let stateService: MockProxy<StateService>; let stateService: MockProxy<StateService>;
let twoFactorService: MockProxy<TwoFactorService>; let twoFactorService: MockProxy<TwoFactorService>;
let authService: MockProxy<AuthService>;
let policyService: MockProxy<PolicyService>; let policyService: MockProxy<PolicyService>;
let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>; let passwordStrengthService: MockProxy<PasswordStrengthServiceAbstraction>;
@@ -64,6 +65,7 @@ describe("PasswordLoginStrategy", () => {
let tokenResponse: IdentityTokenResponse; let tokenResponse: IdentityTokenResponse;
beforeEach(async () => { beforeEach(async () => {
loginStrategyService = mock<LoginStrategyServiceAbstraction>();
cryptoService = mock<CryptoService>(); cryptoService = mock<CryptoService>();
apiService = mock<ApiService>(); apiService = mock<ApiService>();
tokenService = mock<TokenService>(); tokenService = mock<TokenService>();
@@ -73,14 +75,13 @@ describe("PasswordLoginStrategy", () => {
logService = mock<LogService>(); logService = mock<LogService>();
stateService = mock<StateService>(); stateService = mock<StateService>();
twoFactorService = mock<TwoFactorService>(); twoFactorService = mock<TwoFactorService>();
authService = mock<AuthService>();
policyService = mock<PolicyService>(); policyService = mock<PolicyService>();
passwordStrengthService = mock<PasswordStrengthService>(); passwordStrengthService = mock<PasswordStrengthService>();
appIdService.getAppId.mockResolvedValue(deviceId); appIdService.getAppId.mockResolvedValue(deviceId);
tokenService.decodeToken.mockResolvedValue({}); tokenService.decodeToken.mockResolvedValue({});
authService.makePreloginKey.mockResolvedValue(masterKey); loginStrategyService.makePreloginKey.mockResolvedValue(masterKey);
cryptoService.hashMasterKey cryptoService.hashMasterKey
.calledWith(masterPassword, expect.anything(), undefined) .calledWith(masterPassword, expect.anything(), undefined)
@@ -103,7 +104,7 @@ describe("PasswordLoginStrategy", () => {
twoFactorService, twoFactorService,
passwordStrengthService, passwordStrengthService,
policyService, policyService,
authService, loginStrategyService,
); );
credentials = new PasswordLoginCredentials(email, masterPassword); credentials = new PasswordLoginCredentials(email, masterPassword);
tokenResponse = identityTokenResponseFactory(masterPasswordPolicy); tokenResponse = identityTokenResponseFactory(masterPasswordPolicy);

View File

@@ -1,26 +1,27 @@
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction"; import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { MasterPasswordPolicyOptions } from "../../admin-console/models/domain/master-password-policy-options"; import { MasterPasswordPolicyOptions } from "@bitwarden/common/admin-console/models/domain/master-password-policy-options";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { LogService } from "../../platform/abstractions/log.service"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { PasswordTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/password-token.request";
import { StateService } from "../../platform/abstractions/state.service"; import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
import { HashPurpose } from "../../platform/enums"; import { IdentityCaptchaResponse } from "@bitwarden/common/auth/models/response/identity-captcha.response";
import { PasswordStrengthServiceAbstraction } from "../../tools/password-strength"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { MasterKey } from "../../types/key"; import { IdentityTwoFactorResponse } from "@bitwarden/common/auth/models/response/identity-two-factor.response";
import { AuthService } from "../abstractions/auth.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { TokenService } from "../abstractions/token.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { AuthResult } from "../models/domain/auth-result"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { ForceSetPasswordReason } from "../models/domain/force-set-password-reason"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { HashPurpose } from "@bitwarden/common/platform/enums";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { MasterKey } from "@bitwarden/common/types/key";
import { LoginStrategyServiceAbstraction } from "../abstractions";
import { PasswordLoginCredentials } from "../models/domain/login-credentials"; import { PasswordLoginCredentials } from "../models/domain/login-credentials";
import { PasswordTokenRequest } from "../models/request/identity-token/password-token.request";
import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request";
import { IdentityCaptchaResponse } from "../models/response/identity-captcha.response";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { IdentityTwoFactorResponse } from "../models/response/identity-two-factor.response";
import { LoginStrategy } from "./login.strategy"; import { LoginStrategy } from "./login.strategy";
@@ -56,7 +57,7 @@ export class PasswordLoginStrategy extends LoginStrategy {
twoFactorService: TwoFactorService, twoFactorService: TwoFactorService,
private passwordStrengthService: PasswordStrengthServiceAbstraction, private passwordStrengthService: PasswordStrengthServiceAbstraction,
private policyService: PolicyService, private policyService: PolicyService,
private authService: AuthService, private loginStrategyService: LoginStrategyServiceAbstraction,
) { ) {
super( super(
cryptoService, cryptoService,
@@ -94,7 +95,7 @@ export class PasswordLoginStrategy extends LoginStrategy {
override async logIn(credentials: PasswordLoginCredentials) { override async logIn(credentials: PasswordLoginCredentials) {
const { email, masterPassword, captchaToken, twoFactor } = credentials; const { email, masterPassword, captchaToken, twoFactor } = credentials;
this.masterKey = await this.authService.makePreloginKey(masterPassword, email); this.masterKey = await this.loginStrategyService.makePreloginKey(masterPassword, email);
// Hash the password early (before authentication) so we don't persist it in memory in plaintext // Hash the password early (before authentication) so we don't persist it in memory in plaintext
this.localMasterKeyHash = await this.cryptoService.hashMasterKey( this.localMasterKeyHash = await this.cryptoService.hashMasterKey(

View File

@@ -1,25 +1,26 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { I18nService } from "../../platform/abstractions/i18n.service"; import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { LogService } from "../../platform/abstractions/log.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { StateService } from "../../platform/abstractions/state.service"; import { IUserDecryptionOptionsServerResponse } from "@bitwarden/common/auth/models/response/user-decryption-options/user-decryption-options.response";
import { Utils } from "../../platform/misc/utils"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { CsprngArray } from "../../types/csprng"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { DeviceKey, UserKey, MasterKey } from "../../types/key"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { AuthRequestCryptoServiceAbstraction } from "../abstractions/auth-request-crypto.service.abstraction"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { DeviceTrustCryptoServiceAbstraction } from "../abstractions/device-trust-crypto.service.abstraction"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { KeyConnectorService } from "../abstractions/key-connector.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { TokenService } from "../abstractions/token.service"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { CsprngArray } from "@bitwarden/common/types/csprng";
import { DeviceKey, UserKey, MasterKey } from "@bitwarden/common/types/key";
import { SsoLoginCredentials } from "../models/domain/login-credentials"; import { SsoLoginCredentials } from "../models/domain/login-credentials";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { IUserDecryptionOptionsServerResponse } from "../models/response/user-decryption-options/user-decryption-options.response";
import { identityTokenResponseFactory } from "./login.strategy.spec"; import { identityTokenResponseFactory } from "./login.strategy.spec";
import { SsoLoginStrategy } from "./sso-login.strategy"; import { SsoLoginStrategy } from "./sso-login.strategy";

View File

@@ -1,23 +1,24 @@
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuthRequestResponse } from "../../auth/models/response/auth-request.response"; import { AuthRequestCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-crypto.service.abstraction";
import { HttpStatusCode } from "../../enums"; import { DeviceTrustCryptoServiceAbstraction } from "@bitwarden/common/auth/abstractions/device-trust-crypto.service.abstraction";
import { ErrorResponse } from "../../models/response/error.response"; import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { I18nService } from "../../platform/abstractions/i18n.service"; import { ForceSetPasswordReason } from "@bitwarden/common/auth/models/domain/force-set-password-reason";
import { LogService } from "../../platform/abstractions/log.service"; import { SsoTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/sso-token.request";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { AuthRequestResponse } from "@bitwarden/common/auth/models/response/auth-request.response";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { StateService } from "../../platform/abstractions/state.service"; import { HttpStatusCode } from "@bitwarden/common/enums";
import { AuthRequestCryptoServiceAbstraction } from "../abstractions/auth-request-crypto.service.abstraction"; import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { DeviceTrustCryptoServiceAbstraction } from "../abstractions/device-trust-crypto.service.abstraction"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { KeyConnectorService } from "../abstractions/key-connector.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { TokenService } from "../abstractions/token.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { ForceSetPasswordReason } from "../models/domain/force-set-password-reason"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { SsoLoginCredentials } from "../models/domain/login-credentials"; import { SsoLoginCredentials } from "../models/domain/login-credentials";
import { SsoTokenRequest } from "../models/request/identity-token/sso-token.request";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { LoginStrategy } from "./login.strategy"; import { LoginStrategy } from "./login.strategy";

View File

@@ -1,20 +1,21 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { EnvironmentService } from "../../platform/abstractions/environment.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { LogService } from "../../platform/abstractions/log.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { StateService } from "../../platform/abstractions/state.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { Utils } from "../../platform/misc/utils"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { CsprngArray } from "../../types/csprng"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { UserKey, MasterKey } from "../../types/key"; import { Utils } from "@bitwarden/common/platform/misc/utils";
import { KeyConnectorService } from "../abstractions/key-connector.service"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { TokenService } from "../abstractions/token.service"; import { CsprngArray } from "@bitwarden/common/types/csprng";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { UserKey, MasterKey } from "@bitwarden/common/types/key";
import { UserApiLoginCredentials } from "../models/domain/login-credentials"; import { UserApiLoginCredentials } from "../models/domain/login-credentials";
import { identityTokenResponseFactory } from "./login.strategy.spec"; import { identityTokenResponseFactory } from "./login.strategy.spec";

View File

@@ -1,17 +1,18 @@
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { TokenService } from "../../auth/abstractions/token.service"; import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { TwoFactorService } from "../../auth/abstractions/two-factor.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { UserApiTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/user-api-token.request";
import { EnvironmentService } from "../../platform/abstractions/environment.service"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { LogService } from "../../platform/abstractions/log.service"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { StateService } from "../../platform/abstractions/state.service"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { KeyConnectorService } from "../abstractions/key-connector.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { UserApiLoginCredentials } from "../models/domain/login-credentials"; import { UserApiLoginCredentials } from "../models/domain/login-credentials";
import { UserApiTokenRequest } from "../models/request/identity-token/user-api-token.request";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { LoginStrategy } from "./login.strategy"; import { LoginStrategy } from "./login.strategy";

View File

@@ -1,22 +1,23 @@
import { mock, MockProxy } from "jest-mock-extended"; import { mock, MockProxy } from "jest-mock-extended";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "../../platform/abstractions/app-id.service"; import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { LogService } from "../../platform/abstractions/log.service"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service"; import { IUserDecryptionOptionsServerResponse } from "@bitwarden/common/auth/models/response/user-decryption-options/user-decryption-options.response";
import { StateService } from "../../platform/abstractions/state.service"; import { WebAuthnLoginAssertionResponseRequest } from "@bitwarden/common/auth/services/webauthn-login/request/webauthn-login-assertion-response.request";
import { Utils } from "../../platform/misc/utils"; import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { PrfKey, UserKey } from "../../types/key"; import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { TokenService } from "../abstractions/token.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { TwoFactorService } from "../abstractions/two-factor.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { AuthResult } from "../models/domain/auth-result"; 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 { PrfKey, UserKey } from "@bitwarden/common/types/key";
import { WebAuthnLoginCredentials } from "../models/domain/login-credentials"; import { WebAuthnLoginCredentials } from "../models/domain/login-credentials";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { IUserDecryptionOptionsServerResponse } from "../models/response/user-decryption-options/user-decryption-options.response";
import { WebAuthnLoginAssertionResponseRequest } from "../services/webauthn-login/request/webauthn-login-assertion-response.request";
import { identityTokenResponseFactory } from "./login.strategy.spec"; import { identityTokenResponseFactory } from "./login.strategy.spec";
import { WebAuthnLoginStrategy } from "./webauthn-login.strategy"; import { WebAuthnLoginStrategy } from "./webauthn-login.strategy";

View File

@@ -1,9 +1,10 @@
import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypto-key"; import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
import { UserKey } from "../../types/key"; import { WebAuthnLoginTokenRequest } from "@bitwarden/common/auth/models/request/identity-token/webauthn-login-token.request";
import { AuthResult } from "../models/domain/auth-result"; import { IdentityTokenResponse } from "@bitwarden/common/auth/models/response/identity-token.response";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { UserKey } from "@bitwarden/common/types/key";
import { WebAuthnLoginCredentials } from "../models/domain/login-credentials"; import { WebAuthnLoginCredentials } from "../models/domain/login-credentials";
import { WebAuthnLoginTokenRequest } from "../models/request/identity-token/webauthn-login-token.request";
import { IdentityTokenResponse } from "../models/response/identity-token.response";
import { LoginStrategy } from "./login.strategy"; import { LoginStrategy } from "./login.strategy";

View File

@@ -1 +1,2 @@
export * from "./rotateable-key-set"; export * from "./rotateable-key-set";
export * from "./login-credentials";

View File

@@ -1,8 +1,8 @@
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
import { UserKey, MasterKey } from "../../../types/key"; import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/identity-token/token-two-factor.request";
import { AuthenticationType } from "../../enums/authentication-type"; import { WebAuthnLoginAssertionResponseRequest } from "@bitwarden/common/auth/services/webauthn-login/request/webauthn-login-assertion-response.request";
import { WebAuthnLoginAssertionResponseRequest } from "../../services/webauthn-login/request/webauthn-login-assertion-response.request"; import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { TokenTwoFactorRequest } from "../request/identity-token/token-two-factor.request"; import { UserKey, MasterKey } from "@bitwarden/common/types/key";
export class PasswordLoginCredentials { export class PasswordLoginCredentials {
readonly type = AuthenticationType.Password; readonly type = AuthenticationType.Password;

View File

@@ -1 +1,2 @@
export * from "./pin-crypto/pin-crypto.service.implementation"; export * from "./pin-crypto/pin-crypto.service.implementation";
export * from "./login-strategies/login-strategy.service";

View File

@@ -0,0 +1,359 @@
import { Observable, Subject } from "rxjs";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
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 { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { TwoFactorService } from "@bitwarden/common/auth/abstractions/two-factor.service";
import { AuthenticationType } from "@bitwarden/common/auth/enums/authentication-type";
import { AuthResult } from "@bitwarden/common/auth/models/domain/auth-result";
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 { 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 { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { AuthRequestPushNotification } from "@bitwarden/common/models/response/notification.response";
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
import { KdfType } from "@bitwarden/common/platform/enums";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
import { MasterKey } from "@bitwarden/common/types/key";
import { LoginStrategyServiceAbstraction } from "../../abstractions";
import { AuthRequestLoginStrategy } from "../../login-strategies/auth-request-login.strategy";
import { PasswordLoginStrategy } from "../../login-strategies/password-login.strategy";
import { SsoLoginStrategy } from "../../login-strategies/sso-login.strategy";
import { UserApiLoginStrategy } from "../../login-strategies/user-api-login.strategy";
import { WebAuthnLoginStrategy } from "../../login-strategies/webauthn-login.strategy";
import {
UserApiLoginCredentials,
PasswordLoginCredentials,
SsoLoginCredentials,
AuthRequestLoginCredentials,
WebAuthnLoginCredentials,
} from "../../models";
const sessionTimeoutLength = 2 * 60 * 1000; // 2 minutes
export class LoginStrategyService implements LoginStrategyServiceAbstraction {
get email(): string {
if (
this.logInStrategy instanceof PasswordLoginStrategy ||
this.logInStrategy instanceof AuthRequestLoginStrategy ||
this.logInStrategy instanceof SsoLoginStrategy
) {
return this.logInStrategy.email;
}
return null;
}
get masterPasswordHash(): string {
return this.logInStrategy instanceof PasswordLoginStrategy
? this.logInStrategy.masterPasswordHash
: null;
}
get accessCode(): string {
return this.logInStrategy instanceof AuthRequestLoginStrategy
? this.logInStrategy.accessCode
: null;
}
get authRequestId(): string {
return this.logInStrategy instanceof AuthRequestLoginStrategy
? this.logInStrategy.authRequestId
: null;
}
get ssoEmail2FaSessionToken(): string {
return this.logInStrategy instanceof SsoLoginStrategy
? this.logInStrategy.ssoEmail2FaSessionToken
: null;
}
private logInStrategy:
| UserApiLoginStrategy
| PasswordLoginStrategy
| SsoLoginStrategy
| AuthRequestLoginStrategy
| WebAuthnLoginStrategy;
private sessionTimeout: any;
private pushNotificationSubject = new Subject<string>();
constructor(
protected cryptoService: CryptoService,
protected apiService: ApiService,
protected tokenService: TokenService,
protected appIdService: AppIdService,
protected platformUtilsService: PlatformUtilsService,
protected messagingService: MessagingService,
protected logService: LogService,
protected keyConnectorService: KeyConnectorService,
protected environmentService: EnvironmentService,
protected stateService: StateService,
protected twoFactorService: TwoFactorService,
protected i18nService: I18nService,
protected encryptService: EncryptService,
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
protected policyService: PolicyService,
protected deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
protected authReqCryptoService: AuthRequestCryptoServiceAbstraction,
) {}
async logIn(
credentials:
| UserApiLoginCredentials
| PasswordLoginCredentials
| SsoLoginCredentials
| AuthRequestLoginCredentials
| WebAuthnLoginCredentials,
): Promise<AuthResult> {
this.clearState();
let strategy:
| UserApiLoginStrategy
| PasswordLoginStrategy
| SsoLoginStrategy
| AuthRequestLoginStrategy
| WebAuthnLoginStrategy;
switch (credentials.type) {
case AuthenticationType.Password:
strategy = new PasswordLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.passwordStrengthService,
this.policyService,
this,
);
break;
case AuthenticationType.Sso:
strategy = new SsoLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.keyConnectorService,
this.deviceTrustCryptoService,
this.authReqCryptoService,
this.i18nService,
);
break;
case AuthenticationType.UserApi:
strategy = new UserApiLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.environmentService,
this.keyConnectorService,
);
break;
case AuthenticationType.AuthRequest:
strategy = new AuthRequestLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.deviceTrustCryptoService,
);
break;
case AuthenticationType.WebAuthn:
strategy = new WebAuthnLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
);
break;
}
// Note: Do not set the credentials object directly on the strategy. They are
// created in the popup and can cause DeadObject references on Firefox.
const result = await strategy.logIn(credentials as any);
if (result?.requiresTwoFactor) {
this.saveState(strategy);
}
return result;
}
async logInTwoFactor(
twoFactor: TokenTwoFactorRequest,
captchaResponse: string,
): Promise<AuthResult> {
if (this.logInStrategy == null) {
throw new Error(this.i18nService.t("sessionTimeout"));
}
try {
const result = await this.logInStrategy.logInTwoFactor(twoFactor, captchaResponse);
// Only clear state if 2FA token has been accepted, otherwise we need to be able to try again
if (!result.requiresTwoFactor && !result.requiresCaptcha) {
this.clearState();
}
return result;
} catch (e) {
// API exceptions are okay, but if there are any unhandled client-side errors then clear state to be safe
if (!(e instanceof ErrorResponse)) {
this.clearState();
}
throw e;
}
}
authingWithUserApiKey(): boolean {
return this.logInStrategy instanceof UserApiLoginStrategy;
}
authingWithSso(): boolean {
return this.logInStrategy instanceof SsoLoginStrategy;
}
authingWithPassword(): boolean {
return this.logInStrategy instanceof PasswordLoginStrategy;
}
authingWithPasswordless(): boolean {
return this.logInStrategy instanceof AuthRequestLoginStrategy;
}
async makePreloginKey(masterPassword: string, email: string): Promise<MasterKey> {
email = email.trim().toLowerCase();
let kdf: KdfType = null;
let kdfConfig: KdfConfig = null;
try {
const preloginResponse = await this.apiService.postPrelogin(new PreloginRequest(email));
if (preloginResponse != null) {
kdf = preloginResponse.kdf;
kdfConfig = new KdfConfig(
preloginResponse.kdfIterations,
preloginResponse.kdfMemory,
preloginResponse.kdfParallelism,
);
}
} catch (e) {
if (e == null || e.statusCode !== 404) {
throw e;
}
}
return await this.cryptoService.makeMasterKey(masterPassword, email, kdf, kdfConfig);
}
async authResponsePushNotification(notification: AuthRequestPushNotification): Promise<any> {
this.pushNotificationSubject.next(notification.id);
}
getPushNotificationObs$(): Observable<any> {
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(
strategy:
| UserApiLoginStrategy
| PasswordLoginStrategy
| SsoLoginStrategy
| AuthRequestLoginStrategy
| WebAuthnLoginStrategy,
) {
this.logInStrategy = strategy;
this.startSessionTimeout();
}
private clearState() {
this.logInStrategy = null;
this.clearSessionTimeout();
}
private startSessionTimeout() {
this.clearSessionTimeout();
this.sessionTimeout = setTimeout(() => this.clearState(), sessionTimeoutLength);
}
private clearSessionTimeout() {
if (this.sessionTimeout != null) {
clearTimeout(this.sessionTimeout);
}
}
}

View File

@@ -1,50 +1,6 @@
import { Observable } from "rxjs";
import { AuthRequestPushNotification } from "../../models/response/notification.response";
import { MasterKey } from "../../types/key";
import { AuthenticationStatus } from "../enums/authentication-status"; import { AuthenticationStatus } from "../enums/authentication-status";
import { AuthResult } from "../models/domain/auth-result";
import {
UserApiLoginCredentials,
PasswordLoginCredentials,
SsoLoginCredentials,
AuthRequestLoginCredentials,
WebAuthnLoginCredentials,
} from "../models/domain/login-credentials";
import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request";
import { AuthRequestResponse } from "../models/response/auth-request.response";
export abstract class AuthService { export abstract class AuthService {
masterPasswordHash: string;
email: string;
accessCode: string;
authRequestId: string;
ssoEmail2FaSessionToken: string;
logIn: (
credentials:
| UserApiLoginCredentials
| PasswordLoginCredentials
| SsoLoginCredentials
| AuthRequestLoginCredentials
| WebAuthnLoginCredentials,
) => Promise<AuthResult>;
logInTwoFactor: (
twoFactor: TokenTwoFactorRequest,
captchaResponse: string,
) => Promise<AuthResult>;
logOut: (callback: () => void) => void;
makePreloginKey: (masterPassword: string, email: string) => Promise<MasterKey>;
authingWithUserApiKey: () => boolean;
authingWithSso: () => boolean;
authingWithPassword: () => boolean;
authingWithPasswordless: () => boolean;
getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>; getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>;
authResponsePushNotification: (notification: AuthRequestPushNotification) => Promise<any>; logOut: (callback: () => void) => void;
passwordlessLogin: (
id: string,
key: string,
requestApproved: boolean,
) => Promise<AuthRequestResponse>;
getPushNotificationObs$: () => Observable<any>;
} }

View File

@@ -6,6 +6,7 @@ import {
} from "@microsoft/signalr"; } from "@microsoft/signalr";
import { MessagePackHubProtocol } from "@microsoft/signalr-protocol-msgpack"; import { MessagePackHubProtocol } from "@microsoft/signalr-protocol-msgpack";
import { LoginStrategyServiceAbstraction } from "../../../../auth/src/common/abstractions/login-strategy.service";
import { import {
AuthRequestPushNotification, AuthRequestPushNotification,
NotificationResponse, NotificationResponse,
@@ -13,7 +14,6 @@ import {
import { EnvironmentService } from "../../platform/abstractions/environment.service"; import { EnvironmentService } from "../../platform/abstractions/environment.service";
import { LogService } from "../../platform/abstractions/log.service"; import { LogService } from "../../platform/abstractions/log.service";
import { AnonymousHubService as AnonymousHubServiceAbstraction } from "../abstractions/anonymous-hub.service"; import { AnonymousHubService as AnonymousHubServiceAbstraction } from "../abstractions/anonymous-hub.service";
import { AuthService } from "../abstractions/auth.service";
export class AnonymousHubService implements AnonymousHubServiceAbstraction { export class AnonymousHubService implements AnonymousHubServiceAbstraction {
private anonHubConnection: HubConnection; private anonHubConnection: HubConnection;
@@ -21,7 +21,7 @@ export class AnonymousHubService implements AnonymousHubServiceAbstraction {
constructor( constructor(
private environmentService: EnvironmentService, private environmentService: EnvironmentService,
private authService: AuthService, private loginStrategyService: LoginStrategyServiceAbstraction,
private logService: LogService, private logService: LogService,
) {} ) {}
@@ -54,7 +54,7 @@ export class AnonymousHubService implements AnonymousHubServiceAbstraction {
} }
private async ProcessNotification(notification: NotificationResponse) { private async ProcessNotification(notification: NotificationResponse) {
await this.authService.authResponsePushNotification( await this.loginStrategyService.authResponsePushNotification(
notification.payload as AuthRequestPushNotification, notification.payload as AuthRequestPushNotification,
); );
} }

View File

@@ -1,269 +1,19 @@
import { Observable, Subject } from "rxjs";
import { ApiService } from "../../abstractions/api.service"; import { ApiService } from "../../abstractions/api.service";
import { PolicyService } from "../../admin-console/abstractions/policy/policy.service.abstraction";
import { PreloginRequest } from "../../models/request/prelogin.request";
import { ErrorResponse } from "../../models/response/error.response";
import { AuthRequestPushNotification } from "../../models/response/notification.response";
import { AppIdService } from "../../platform/abstractions/app-id.service";
import { CryptoService } from "../../platform/abstractions/crypto.service"; import { CryptoService } from "../../platform/abstractions/crypto.service";
import { EncryptService } from "../../platform/abstractions/encrypt.service";
import { EnvironmentService } from "../../platform/abstractions/environment.service";
import { I18nService } from "../../platform/abstractions/i18n.service";
import { LogService } from "../../platform/abstractions/log.service";
import { MessagingService } from "../../platform/abstractions/messaging.service"; import { MessagingService } from "../../platform/abstractions/messaging.service";
import { PlatformUtilsService } from "../../platform/abstractions/platform-utils.service";
import { StateService } from "../../platform/abstractions/state.service"; import { StateService } from "../../platform/abstractions/state.service";
import { KdfType, KeySuffixOptions } from "../../platform/enums"; import { KeySuffixOptions } from "../../platform/enums";
import { Utils } from "../../platform/misc/utils";
import { PasswordStrengthServiceAbstraction } from "../../tools/password-strength";
import { MasterKey } from "../../types/key";
import { AuthRequestCryptoServiceAbstraction } from "../abstractions/auth-request-crypto.service.abstraction";
import { AuthService as AuthServiceAbstraction } from "../abstractions/auth.service"; import { AuthService as AuthServiceAbstraction } from "../abstractions/auth.service";
import { DeviceTrustCryptoServiceAbstraction } from "../abstractions/device-trust-crypto.service.abstraction";
import { KeyConnectorService } from "../abstractions/key-connector.service";
import { TokenService } from "../abstractions/token.service";
import { TwoFactorService } from "../abstractions/two-factor.service";
import { AuthenticationStatus } from "../enums/authentication-status"; import { AuthenticationStatus } from "../enums/authentication-status";
import { AuthenticationType } from "../enums/authentication-type";
import { AuthRequestLoginStrategy } from "../login-strategies/auth-request-login.strategy";
import { PasswordLoginStrategy } from "../login-strategies/password-login.strategy";
import { SsoLoginStrategy } from "../login-strategies/sso-login.strategy";
import { UserApiLoginStrategy } from "../login-strategies/user-api-login.strategy";
import { WebAuthnLoginStrategy } from "../login-strategies/webauthn-login.strategy";
import { AuthResult } from "../models/domain/auth-result";
import { KdfConfig } from "../models/domain/kdf-config";
import {
AuthRequestLoginCredentials,
PasswordLoginCredentials,
SsoLoginCredentials,
UserApiLoginCredentials,
WebAuthnLoginCredentials,
} from "../models/domain/login-credentials";
import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request";
import { PasswordlessAuthRequest } from "../models/request/passwordless-auth.request";
import { AuthRequestResponse } from "../models/response/auth-request.response";
const sessionTimeoutLength = 2 * 60 * 1000; // 2 minutes
export class AuthService implements AuthServiceAbstraction { export class AuthService implements AuthServiceAbstraction {
get email(): string {
if (
this.logInStrategy instanceof PasswordLoginStrategy ||
this.logInStrategy instanceof AuthRequestLoginStrategy ||
this.logInStrategy instanceof SsoLoginStrategy
) {
return this.logInStrategy.email;
}
return null;
}
get masterPasswordHash(): string {
return this.logInStrategy instanceof PasswordLoginStrategy
? this.logInStrategy.masterPasswordHash
: null;
}
get accessCode(): string {
return this.logInStrategy instanceof AuthRequestLoginStrategy
? this.logInStrategy.accessCode
: null;
}
get authRequestId(): string {
return this.logInStrategy instanceof AuthRequestLoginStrategy
? this.logInStrategy.authRequestId
: null;
}
get ssoEmail2FaSessionToken(): string {
return this.logInStrategy instanceof SsoLoginStrategy
? this.logInStrategy.ssoEmail2FaSessionToken
: null;
}
private logInStrategy:
| UserApiLoginStrategy
| PasswordLoginStrategy
| SsoLoginStrategy
| AuthRequestLoginStrategy
| WebAuthnLoginStrategy;
private sessionTimeout: any;
private pushNotificationSubject = new Subject<string>();
constructor( constructor(
protected messagingService: MessagingService,
protected cryptoService: CryptoService, protected cryptoService: CryptoService,
protected apiService: ApiService, protected apiService: ApiService,
protected tokenService: TokenService,
protected appIdService: AppIdService,
protected platformUtilsService: PlatformUtilsService,
protected messagingService: MessagingService,
protected logService: LogService,
protected keyConnectorService: KeyConnectorService,
protected environmentService: EnvironmentService,
protected stateService: StateService, protected stateService: StateService,
protected twoFactorService: TwoFactorService,
protected i18nService: I18nService,
protected encryptService: EncryptService,
protected passwordStrengthService: PasswordStrengthServiceAbstraction,
protected policyService: PolicyService,
protected deviceTrustCryptoService: DeviceTrustCryptoServiceAbstraction,
protected authReqCryptoService: AuthRequestCryptoServiceAbstraction,
) {} ) {}
async logIn(
credentials:
| UserApiLoginCredentials
| PasswordLoginCredentials
| SsoLoginCredentials
| AuthRequestLoginCredentials
| WebAuthnLoginCredentials,
): Promise<AuthResult> {
this.clearState();
let strategy:
| UserApiLoginStrategy
| PasswordLoginStrategy
| SsoLoginStrategy
| AuthRequestLoginStrategy
| WebAuthnLoginStrategy;
switch (credentials.type) {
case AuthenticationType.Password:
strategy = new PasswordLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.passwordStrengthService,
this.policyService,
this,
);
break;
case AuthenticationType.Sso:
strategy = new SsoLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.keyConnectorService,
this.deviceTrustCryptoService,
this.authReqCryptoService,
this.i18nService,
);
break;
case AuthenticationType.UserApi:
strategy = new UserApiLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.environmentService,
this.keyConnectorService,
);
break;
case AuthenticationType.AuthRequest:
strategy = new AuthRequestLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
this.deviceTrustCryptoService,
);
break;
case AuthenticationType.WebAuthn:
strategy = new WebAuthnLoginStrategy(
this.cryptoService,
this.apiService,
this.tokenService,
this.appIdService,
this.platformUtilsService,
this.messagingService,
this.logService,
this.stateService,
this.twoFactorService,
);
break;
}
// Note: Do not set the credentials object directly on the strategy. They are
// created in the popup and can cause DeadObject references on Firefox.
const result = await strategy.logIn(credentials as any);
if (result?.requiresTwoFactor) {
this.saveState(strategy);
}
return result;
}
async logInTwoFactor(
twoFactor: TokenTwoFactorRequest,
captchaResponse: string,
): Promise<AuthResult> {
if (this.logInStrategy == null) {
throw new Error(this.i18nService.t("sessionTimeout"));
}
try {
const result = await this.logInStrategy.logInTwoFactor(twoFactor, captchaResponse);
// Only clear state if 2FA token has been accepted, otherwise we need to be able to try again
if (!result.requiresTwoFactor && !result.requiresCaptcha) {
this.clearState();
}
return result;
} catch (e) {
// API exceptions are okay, but if there are any unhandled client-side errors then clear state to be safe
if (!(e instanceof ErrorResponse)) {
this.clearState();
}
throw e;
}
}
logOut(callback: () => void) {
callback();
this.messagingService.send("loggedOut");
}
authingWithUserApiKey(): boolean {
return this.logInStrategy instanceof UserApiLoginStrategy;
}
authingWithSso(): boolean {
return this.logInStrategy instanceof SsoLoginStrategy;
}
authingWithPassword(): boolean {
return this.logInStrategy instanceof PasswordLoginStrategy;
}
authingWithPasswordless(): boolean {
return this.logInStrategy instanceof AuthRequestLoginStrategy;
}
async getAuthStatus(userId?: string): Promise<AuthenticationStatus> { async getAuthStatus(userId?: string): Promise<AuthenticationStatus> {
// If we don't have an access token or userId, we're logged out // If we don't have an access token or userId, we're logged out
const isAuthenticated = await this.stateService.getIsAuthenticated({ userId: userId }); const isAuthenticated = await this.stateService.getIsAuthenticated({ userId: userId });
@@ -298,100 +48,8 @@ export class AuthService implements AuthServiceAbstraction {
return AuthenticationStatus.Unlocked; return AuthenticationStatus.Unlocked;
} }
async makePreloginKey(masterPassword: string, email: string): Promise<MasterKey> { logOut(callback: () => void) {
email = email.trim().toLowerCase(); callback();
let kdf: KdfType = null; this.messagingService.send("loggedOut");
let kdfConfig: KdfConfig = null;
try {
const preloginResponse = await this.apiService.postPrelogin(new PreloginRequest(email));
if (preloginResponse != null) {
kdf = preloginResponse.kdf;
kdfConfig = new KdfConfig(
preloginResponse.kdfIterations,
preloginResponse.kdfMemory,
preloginResponse.kdfParallelism,
);
}
} catch (e) {
if (e == null || e.statusCode !== 404) {
throw e;
}
}
return await this.cryptoService.makeMasterKey(masterPassword, email, kdf, kdfConfig);
}
async authResponsePushNotification(notification: AuthRequestPushNotification): Promise<any> {
this.pushNotificationSubject.next(notification.id);
}
getPushNotificationObs$(): Observable<any> {
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(
strategy:
| UserApiLoginStrategy
| PasswordLoginStrategy
| SsoLoginStrategy
| AuthRequestLoginStrategy
| WebAuthnLoginStrategy,
) {
this.logInStrategy = strategy;
this.startSessionTimeout();
}
private clearState() {
this.logInStrategy = null;
this.clearSessionTimeout();
}
private startSessionTimeout() {
this.clearSessionTimeout();
this.sessionTimeout = setTimeout(() => this.clearState(), sessionTimeoutLength);
}
private clearSessionTimeout() {
if (this.sessionTimeout != null) {
clearTimeout(this.sessionTimeout);
}
} }
} }

View File

@@ -1,16 +1,16 @@
import { mock } from "jest-mock-extended"; import { mock } from "jest-mock-extended";
import { firstValueFrom, of } from "rxjs"; import { firstValueFrom, of } from "rxjs";
import { LoginStrategyServiceAbstraction, WebAuthnLoginCredentials } from "@bitwarden/auth/common";
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction"; import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction";
import { LogService } from "../../../platform/abstractions/log.service"; import { LogService } from "../../../platform/abstractions/log.service";
import { Utils } from "../../../platform/misc/utils"; import { Utils } from "../../../platform/misc/utils";
import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key"; import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-crypto-key";
import { PrfKey } from "../../../types/key"; import { PrfKey } from "../../../types/key";
import { AuthService } from "../../abstractions/auth.service";
import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction"; import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction";
import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction"; import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction";
import { AuthResult } from "../../models/domain/auth-result"; import { AuthResult } from "../../models/domain/auth-result";
import { WebAuthnLoginCredentials } from "../../models/domain/login-credentials";
import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view"; import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view";
import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion.view"; import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion.view";
@@ -22,7 +22,7 @@ describe("WebAuthnLoginService", () => {
let webAuthnLoginService: WebAuthnLoginService; let webAuthnLoginService: WebAuthnLoginService;
const webAuthnLoginApiService = mock<WebAuthnLoginApiServiceAbstraction>(); const webAuthnLoginApiService = mock<WebAuthnLoginApiServiceAbstraction>();
const authService = mock<AuthService>(); const loginStrategyService = mock<LoginStrategyServiceAbstraction>();
const configService = mock<ConfigServiceAbstraction>(); const configService = mock<ConfigServiceAbstraction>();
const webAuthnLoginPrfCryptoService = mock<WebAuthnLoginPrfCryptoServiceAbstraction>(); const webAuthnLoginPrfCryptoService = mock<WebAuthnLoginPrfCryptoServiceAbstraction>();
const navigatorCredentials = mock<CredentialsContainer>(); const navigatorCredentials = mock<CredentialsContainer>();
@@ -75,7 +75,7 @@ describe("WebAuthnLoginService", () => {
configService.getFeatureFlag$.mockReturnValue(of(config.featureEnabled)); configService.getFeatureFlag$.mockReturnValue(of(config.featureEnabled));
return new WebAuthnLoginService( return new WebAuthnLoginService(
webAuthnLoginApiService, webAuthnLoginApiService,
authService, loginStrategyService,
configService, configService,
webAuthnLoginPrfCryptoService, webAuthnLoginPrfCryptoService,
window, window,
@@ -273,7 +273,7 @@ describe("WebAuthnLoginService", () => {
const assertion = buildWebAuthnLoginCredentialAssertionView(); const assertion = buildWebAuthnLoginCredentialAssertionView();
const mockAuthResult: AuthResult = new AuthResult(); const mockAuthResult: AuthResult = new AuthResult();
jest.spyOn(authService, "logIn").mockResolvedValue(mockAuthResult); jest.spyOn(loginStrategyService, "logIn").mockResolvedValue(mockAuthResult);
// Act // Act
const result = await webAuthnLoginService.logIn(assertion); const result = await webAuthnLoginService.logIn(assertion);
@@ -281,7 +281,7 @@ describe("WebAuthnLoginService", () => {
// Assert // Assert
expect(result).toEqual(mockAuthResult); expect(result).toEqual(mockAuthResult);
const callArguments = authService.logIn.mock.calls[0]; const callArguments = loginStrategyService.logIn.mock.calls[0];
expect(callArguments[0]).toBeInstanceOf(WebAuthnLoginCredentials); expect(callArguments[0]).toBeInstanceOf(WebAuthnLoginCredentials);
}); });
}); });

View File

@@ -1,15 +1,15 @@
import { Observable } from "rxjs"; import { Observable } from "rxjs";
import { LoginStrategyServiceAbstraction, WebAuthnLoginCredentials } from "@bitwarden/auth/common";
import { FeatureFlag } from "../../../enums/feature-flag.enum"; import { FeatureFlag } from "../../../enums/feature-flag.enum";
import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction"; import { ConfigServiceAbstraction } from "../../../platform/abstractions/config/config.service.abstraction";
import { LogService } from "../../../platform/abstractions/log.service"; import { LogService } from "../../../platform/abstractions/log.service";
import { PrfKey } from "../../../types/key"; import { PrfKey } from "../../../types/key";
import { AuthService } from "../../abstractions/auth.service";
import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction"; import { WebAuthnLoginApiServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-api.service.abstraction";
import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction"; import { WebAuthnLoginPrfCryptoServiceAbstraction } from "../../abstractions/webauthn/webauthn-login-prf-crypto.service.abstraction";
import { WebAuthnLoginServiceAbstraction } from "../../abstractions/webauthn/webauthn-login.service.abstraction"; import { WebAuthnLoginServiceAbstraction } from "../../abstractions/webauthn/webauthn-login.service.abstraction";
import { AuthResult } from "../../models/domain/auth-result"; import { AuthResult } from "../../models/domain/auth-result";
import { WebAuthnLoginCredentials } from "../../models/domain/login-credentials";
import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view"; import { WebAuthnLoginCredentialAssertionOptionsView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion-options.view";
import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion.view"; import { WebAuthnLoginCredentialAssertionView } from "../../models/view/webauthn-login/webauthn-login-credential-assertion.view";
@@ -22,7 +22,7 @@ export class WebAuthnLoginService implements WebAuthnLoginServiceAbstraction {
constructor( constructor(
private webAuthnLoginApiService: WebAuthnLoginApiServiceAbstraction, private webAuthnLoginApiService: WebAuthnLoginApiServiceAbstraction,
private authService: AuthService, private loginStrategyService: LoginStrategyServiceAbstraction,
private configService: ConfigServiceAbstraction, private configService: ConfigServiceAbstraction,
private webAuthnLoginPrfCryptoService: WebAuthnLoginPrfCryptoServiceAbstraction, private webAuthnLoginPrfCryptoService: WebAuthnLoginPrfCryptoServiceAbstraction,
private window: Window, private window: Window,
@@ -86,7 +86,7 @@ export class WebAuthnLoginService implements WebAuthnLoginServiceAbstraction {
assertion.deviceResponse, assertion.deviceResponse,
assertion.prfKey, assertion.prfKey,
); );
const result = await this.authService.logIn(credential); const result = await this.loginStrategyService.logIn(credential);
return result; return result;
} }
} }