import { ApiService } from "../../abstractions/api.service"; import { AppIdService } from "../../abstractions/appId.service"; import { CryptoService } from "../../abstractions/crypto.service"; import { LogService } from "../../abstractions/log.service"; import { MessagingService } from "../../abstractions/messaging.service"; import { PlatformUtilsService } from "../../abstractions/platformUtils.service"; import { StateService } from "../../abstractions/state.service"; import { HashPurpose } from "../../enums"; import { SymmetricCryptoKey } from "../../models/domain/symmetric-crypto-key"; import { AuthService } from "../abstractions/auth.service"; import { TokenService } from "../abstractions/token.service"; import { TwoFactorService } from "../abstractions/two-factor.service"; import { AuthResult } from "../models/domain/auth-result"; import { PasswordLogInCredentials } from "../models/domain/log-in-credentials"; import { PasswordTokenRequest } from "../models/request/identity-token/password-token.request"; import { TokenTwoFactorRequest } from "../models/request/identity-token/token-two-factor.request"; import { LogInStrategy } from "./login.strategy"; export class PasswordLogInStrategy extends LogInStrategy { get email() { return this.tokenRequest.email; } get masterPasswordHash() { return this.tokenRequest.masterPasswordHash; } tokenRequest: PasswordTokenRequest; private localHashedPassword: string; private key: SymmetricCryptoKey; constructor( cryptoService: CryptoService, apiService: ApiService, tokenService: TokenService, appIdService: AppIdService, platformUtilsService: PlatformUtilsService, messagingService: MessagingService, logService: LogService, stateService: StateService, twoFactorService: TwoFactorService, private authService: AuthService ) { super( cryptoService, apiService, tokenService, appIdService, platformUtilsService, messagingService, logService, stateService, twoFactorService ); } async setUserKey() { await this.cryptoService.setKey(this.key); await this.cryptoService.setKeyHash(this.localHashedPassword); } async logInTwoFactor( twoFactor: TokenTwoFactorRequest, captchaResponse: string ): Promise { this.tokenRequest.captchaResponse = captchaResponse ?? this.captchaBypassToken; return super.logInTwoFactor(twoFactor); } async logIn(credentials: PasswordLogInCredentials) { const { email, masterPassword, captchaToken, twoFactor } = credentials; this.key = await this.authService.makePreloginKey(masterPassword, email); // Hash the password early (before authentication) so we don't persist it in memory in plaintext this.localHashedPassword = await this.cryptoService.hashPassword( masterPassword, this.key, HashPurpose.LocalAuthorization ); const hashedPassword = await this.cryptoService.hashPassword(masterPassword, this.key); this.tokenRequest = new PasswordTokenRequest( email, hashedPassword, captchaToken, await this.buildTwoFactor(twoFactor), await this.buildDeviceRequest() ); return this.startLogIn(); } }