From f740d8b05783701f29eb3f0709888c4b4f69d92e Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Wed, 17 Nov 2021 09:37:36 +1000 Subject: [PATCH] Update jslib and use new UserVerificationService pattern (#1302) * Use try/catch pattern for userVerification * Update deps --- jslib | 2 +- .../settings/delete-organization.component.ts | 5 +- src/app/services/services.module.ts | 5 +- src/app/settings/api-key.component.ts | 5 +- .../deauthorize-sessions.component.ts | 5 +- src/app/settings/delete-account.component.ts | 5 +- src/app/settings/purge-vault.component.ts | 5 +- .../settings/two-factor-verify.component.ts | 74 +++++++++++-------- 8 files changed, 58 insertions(+), 48 deletions(-) diff --git a/jslib b/jslib index e02e663ce1..720967475b 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit e02e663ce1aed94d42db00dcdb2e42bdd625f0dc +Subproject commit 720967475b37d635c18a1eb74bb3702445647b4d diff --git a/src/app/organizations/settings/delete-organization.component.ts b/src/app/organizations/settings/delete-organization.component.ts index fe6a14b792..4ab47c9878 100644 --- a/src/app/organizations/settings/delete-organization.component.ts +++ b/src/app/organizations/settings/delete-organization.component.ts @@ -25,10 +25,9 @@ export class DeleteOrganizationComponent { private router: Router, private logService: LogService) { } async submit() { - const request = await this.userVerificationService.buildRequest(this.masterPassword); - try { - this.formPromise = this.apiService.deleteOrganization(this.organizationId, request); + this.formPromise = this.userVerificationService.buildRequest(this.masterPassword) + .then(request => this.apiService.deleteOrganization(this.organizationId, request)); await this.formPromise; this.toasterService.popAsync('success', this.i18nService.t('organizationDeleted'), this.i18nService.t('organizationDeletedDesc')); diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts index 336d911d7d..9064202ef5 100644 --- a/src/app/services/services.module.ts +++ b/src/app/services/services.module.ts @@ -129,7 +129,7 @@ const policyService = new PolicyService(userService, storageService, apiService) const sendService = new SendService(cryptoService, userService, apiService, fileUploadService, storageService, i18nService, cryptoFunctionService); const keyConnectorService = new KeyConnectorService(storageService, userService, cryptoService, apiService, - environmentService, tokenService, consoleLogService); + tokenService, consoleLogService); const vaultTimeoutService = new VaultTimeoutService(cipherService, folderService, collectionService, cryptoService, platformUtilsService, storageService, messagingService, searchService, userService, tokenService, policyService, keyConnectorService, null, async () => messagingService.send('logout', { expired: false })); @@ -150,6 +150,7 @@ const notificationsService = new NotificationsService(userService, syncService, environmentService, async () => messagingService.send('logout', { expired: true }), consoleLogService); const auditService = new AuditService(cryptoFunctionService, apiService); const eventLoggingService = new EventLoggingService(storageService, apiService, userService, cipherService, consoleLogService); +const userVerificationService = new UserVerificationService(cryptoService, i18nService, apiService); containerService.attachToWindow(window); @@ -234,8 +235,8 @@ export function initFactory(): Function { { provide: PolicyServiceAbstraction, useValue: policyService }, { provide: SendServiceAbstraction, useValue: sendService }, { provide: KeyConnectorServiceAbstraction, useValue: keyConnectorService }, + { provide: UserVerificationServiceAbstraction, useValue: userVerificationService }, { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, - { provide: UserVerificationServiceAbstraction, useClass: UserVerificationService }, { provide: LogService, useValue: consoleLogService }, { provide: APP_INITIALIZER, diff --git a/src/app/settings/api-key.component.ts b/src/app/settings/api-key.component.ts index 5dd8903c22..b658dbf8ee 100644 --- a/src/app/settings/api-key.component.ts +++ b/src/app/settings/api-key.component.ts @@ -32,10 +32,9 @@ export class ApiKeyComponent { constructor(private userVerificationService: UserVerificationService, private logService: LogService) { } async submit() { - const request = await this.userVerificationService.buildRequest(this.masterPassword); - try { - this.formPromise = this.postKey(this.entityId, request); + this.formPromise = this.userVerificationService.buildRequest(this.masterPassword) + .then(request => this.postKey(this.entityId, request)); const response = await this.formPromise; this.clientSecret = response.apiKey; this.clientId = `${this.keyType}.${this.entityId}`; diff --git a/src/app/settings/deauthorize-sessions.component.ts b/src/app/settings/deauthorize-sessions.component.ts index 3a0cff47b9..05301f49f9 100644 --- a/src/app/settings/deauthorize-sessions.component.ts +++ b/src/app/settings/deauthorize-sessions.component.ts @@ -23,10 +23,9 @@ export class DeauthorizeSessionsComponent { private messagingService: MessagingService, private logService: LogService) { } async submit() { - const request = await this.userVerificationService.buildRequest(this.masterPassword); - try { - this.formPromise = this.apiService.postSecurityStamp(request); + this.formPromise = this.userVerificationService.buildRequest(this.masterPassword) + .then(request => this.apiService.postSecurityStamp(request)); await this.formPromise; this.toasterService.popAsync('success', this.i18nService.t('sessionsDeauthorized'), this.i18nService.t('logBackIn')); diff --git a/src/app/settings/delete-account.component.ts b/src/app/settings/delete-account.component.ts index 0e839291c1..af4890821a 100644 --- a/src/app/settings/delete-account.component.ts +++ b/src/app/settings/delete-account.component.ts @@ -23,10 +23,9 @@ export class DeleteAccountComponent { private messagingService: MessagingService, private logService: LogService) { } async submit() { - const request = await this.userVerificationService.buildRequest(this.masterPassword); - try { - this.formPromise = this.apiService.deleteAccount(request); + this.formPromise = this.userVerificationService.buildRequest(this.masterPassword) + .then(request => this.apiService.deleteAccount(request)); await this.formPromise; this.toasterService.popAsync('success', this.i18nService.t('accountDeleted'), this.i18nService.t('accountDeletedDesc')); diff --git a/src/app/settings/purge-vault.component.ts b/src/app/settings/purge-vault.component.ts index 130f9d4a59..14c9f9c8d7 100644 --- a/src/app/settings/purge-vault.component.ts +++ b/src/app/settings/purge-vault.component.ts @@ -28,10 +28,9 @@ export class PurgeVaultComponent { private router: Router, private logService: LogService) { } async submit() { - const request = await this.userVerificationService.buildRequest(this.masterPassword); - try { - this.formPromise = this.apiService.postPurgeCiphers(request, this.organizationId); + this.formPromise = this.userVerificationService.buildRequest(this.masterPassword) + .then(request => this.apiService.postPurgeCiphers(request, this.organizationId)); await this.formPromise; this.toasterService.popAsync('success', null, this.i18nService.t('vaultPurged')); if (this.organizationId != null) { diff --git a/src/app/settings/two-factor-verify.component.ts b/src/app/settings/two-factor-verify.component.ts index e92d7d016c..1e9f394851 100644 --- a/src/app/settings/two-factor-verify.component.ts +++ b/src/app/settings/two-factor-verify.component.ts @@ -14,6 +14,18 @@ import { UserVerificationService } from 'jslib-common/abstractions/userVerificat import { Verification } from 'jslib-common/types/verification'; +import { TwoFactorAuthenticatorResponse } from 'jslib-common/models/response/twoFactorAuthenticatorResponse'; +import { TwoFactorDuoResponse } from 'jslib-common/models/response/twoFactorDuoResponse'; +import { TwoFactorEmailResponse } from 'jslib-common/models/response/twoFactorEmailResponse'; +import { TwoFactorRecoverResponse } from 'jslib-common/models/response/twoFactorRescoverResponse'; +import { TwoFactorWebAuthnResponse } from 'jslib-common/models/response/twoFactorWebAuthnResponse'; +import { TwoFactorYubiKeyResponse } from 'jslib-common/models/response/twoFactorYubiKeyResponse'; + +import { SecretVerificationRequest } from 'jslib-common/models/request/secretVerificationRequest'; + +type TwoFactorResponse = TwoFactorRecoverResponse | TwoFactorDuoResponse | TwoFactorEmailResponse | + TwoFactorWebAuthnResponse | TwoFactorAuthenticatorResponse | TwoFactorYubiKeyResponse; + @Component({ selector: 'app-two-factor-verify', templateUrl: 'two-factor-verify.component.html', @@ -24,51 +36,53 @@ export class TwoFactorVerifyComponent { @Output() onAuthed = new EventEmitter(); secret: Verification; - formPromise: Promise; + formPromise: Promise; constructor(private apiService: ApiService, private logService: LogService, private userVerificationService: UserVerificationService) { } async submit() { - const request = await this.userVerificationService.buildRequest(this.secret); + let hashedSecret: string; try { - switch (this.type) { - case -1: - this.formPromise = this.apiService.getTwoFactorRecover(request); - break; - case TwoFactorProviderType.Duo: - case TwoFactorProviderType.OrganizationDuo: - if (this.organizationId != null) { - this.formPromise = this.apiService.getTwoFactorOrganizationDuo(this.organizationId, request); - } else { - this.formPromise = this.apiService.getTwoFactorDuo(request); - } - break; - case TwoFactorProviderType.Email: - this.formPromise = this.apiService.getTwoFactorEmail(request); - break; - case TwoFactorProviderType.WebAuthn: - this.formPromise = this.apiService.getTwoFactorWebAuthn(request); - break; - case TwoFactorProviderType.Authenticator: - this.formPromise = this.apiService.getTwoFactorAuthenticator(request); - break; - case TwoFactorProviderType.Yubikey: - this.formPromise = this.apiService.getTwoFactorYubiKey(request); - break; - } + this.formPromise = this.userVerificationService.buildRequest(this.secret) + .then(request => { + hashedSecret = this.secret.type === VerificationType.MasterPassword + ? request.masterPasswordHash + : request.otp; + return this.apiCall(request); + }); const response = await this.formPromise; this.onAuthed.emit({ response: response, - secret: this.secret.type === VerificationType.MasterPassword - ? request.masterPasswordHash - : request.otp, + secret: hashedSecret, verificationType: this.secret.type, }); } catch (e) { this.logService.error(e); } } + + private apiCall(request: SecretVerificationRequest): Promise { + switch (this.type) { + case -1: + return this.apiService.getTwoFactorRecover(request); + case TwoFactorProviderType.Duo: + case TwoFactorProviderType.OrganizationDuo: + if (this.organizationId != null) { + return this.apiService.getTwoFactorOrganizationDuo(this.organizationId, request); + } else { + return this.apiService.getTwoFactorDuo(request); + } + case TwoFactorProviderType.Email: + return this.apiService.getTwoFactorEmail(request); + case TwoFactorProviderType.WebAuthn: + return this.apiService.getTwoFactorWebAuthn(request); + case TwoFactorProviderType.Authenticator: + return this.apiService.getTwoFactorAuthenticator(request); + case TwoFactorProviderType.Yubikey: + return this.apiService.getTwoFactorYubiKey(request); + } + } }