// FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { firstValueFrom, map } from "rxjs"; import { TwoFactorApiService } from ".."; import { ListResponse } from "../../../models/response/list.response"; import { I18nService } from "../../../platform/abstractions/i18n.service"; import { PlatformUtilsService } from "../../../platform/abstractions/platform-utils.service"; import { Utils } from "../../../platform/misc/utils"; import { GlobalStateProvider } from "../../../platform/state"; import { TwoFactorProviderType } from "../../enums/two-factor-provider-type"; import { DisableTwoFactorAuthenticatorRequest } from "../../models/request/disable-two-factor-authenticator.request"; import { SecretVerificationRequest } from "../../models/request/secret-verification.request"; import { TwoFactorEmailRequest } from "../../models/request/two-factor-email.request"; import { TwoFactorProviderRequest } from "../../models/request/two-factor-provider.request"; import { UpdateTwoFactorAuthenticatorRequest } from "../../models/request/update-two-factor-authenticator.request"; import { UpdateTwoFactorDuoRequest } from "../../models/request/update-two-factor-duo.request"; import { UpdateTwoFactorEmailRequest } from "../../models/request/update-two-factor-email.request"; import { UpdateTwoFactorWebAuthnDeleteRequest } from "../../models/request/update-two-factor-web-authn-delete.request"; import { UpdateTwoFactorWebAuthnRequest } from "../../models/request/update-two-factor-web-authn.request"; import { UpdateTwoFactorYubikeyOtpRequest } from "../../models/request/update-two-factor-yubikey-otp.request"; import { IdentityTwoFactorResponse } from "../../models/response/identity-two-factor.response"; import { TwoFactorAuthenticatorResponse } from "../../models/response/two-factor-authenticator.response"; import { TwoFactorDuoResponse } from "../../models/response/two-factor-duo.response"; import { TwoFactorEmailResponse } from "../../models/response/two-factor-email.response"; import { TwoFactorProviderResponse } from "../../models/response/two-factor-provider.response"; import { TwoFactorRecoverResponse } from "../../models/response/two-factor-recover.response"; import { TwoFactorWebAuthnResponse, ChallengeResponse, } from "../../models/response/two-factor-web-authn.response"; import { TwoFactorYubiKeyResponse } from "../../models/response/two-factor-yubi-key.response"; import { PROVIDERS, SELECTED_PROVIDER, TwoFactorProviderDetails, TwoFactorProviders, TwoFactorService as TwoFactorServiceAbstraction, } from "../abstractions/two-factor.service"; export class DefaultTwoFactorService implements TwoFactorServiceAbstraction { private providersState = this.globalStateProvider.get(PROVIDERS); private selectedState = this.globalStateProvider.get(SELECTED_PROVIDER); readonly providers$ = this.providersState.state$.pipe( map((providers) => Utils.recordToMap(providers)), ); readonly selected$ = this.selectedState.state$; constructor( private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, private globalStateProvider: GlobalStateProvider, private twoFactorApiService: TwoFactorApiService, ) {} init() { TwoFactorProviders[TwoFactorProviderType.Email].name = this.i18nService.t("emailTitle"); TwoFactorProviders[TwoFactorProviderType.Email].description = this.i18nService.t("emailDescV2"); TwoFactorProviders[TwoFactorProviderType.Authenticator].name = this.i18nService.t("authenticatorAppTitle"); TwoFactorProviders[TwoFactorProviderType.Authenticator].description = this.i18nService.t("authenticatorAppDescV2"); TwoFactorProviders[TwoFactorProviderType.Duo].description = this.i18nService.t("duoDescV2"); TwoFactorProviders[TwoFactorProviderType.OrganizationDuo].name = "Duo (" + this.i18nService.t("organization") + ")"; TwoFactorProviders[TwoFactorProviderType.OrganizationDuo].description = this.i18nService.t("duoOrganizationDesc"); TwoFactorProviders[TwoFactorProviderType.WebAuthn].name = this.i18nService.t("webAuthnTitle"); TwoFactorProviders[TwoFactorProviderType.WebAuthn].description = this.i18nService.t("webAuthnDesc"); TwoFactorProviders[TwoFactorProviderType.Yubikey].name = this.i18nService.t("yubiKeyTitleV2"); TwoFactorProviders[TwoFactorProviderType.Yubikey].description = this.i18nService.t("yubiKeyDesc"); } async getSupportedProviders(win: Window): Promise { const data = await firstValueFrom(this.providers$); const providers: any[] = []; if (data == null) { return providers; } if ( data.has(TwoFactorProviderType.OrganizationDuo) && this.platformUtilsService.supportsDuo() ) { providers.push(TwoFactorProviders[TwoFactorProviderType.OrganizationDuo]); } if (data.has(TwoFactorProviderType.Authenticator)) { providers.push(TwoFactorProviders[TwoFactorProviderType.Authenticator]); } if (data.has(TwoFactorProviderType.Yubikey)) { providers.push(TwoFactorProviders[TwoFactorProviderType.Yubikey]); } if (data.has(TwoFactorProviderType.Duo) && this.platformUtilsService.supportsDuo()) { providers.push(TwoFactorProviders[TwoFactorProviderType.Duo]); } if ( data.has(TwoFactorProviderType.WebAuthn) && this.platformUtilsService.supportsWebAuthn(win) ) { providers.push(TwoFactorProviders[TwoFactorProviderType.WebAuthn]); } if (data.has(TwoFactorProviderType.Email)) { providers.push(TwoFactorProviders[TwoFactorProviderType.Email]); } return providers; } async getDefaultProvider(webAuthnSupported: boolean): Promise { const data = await firstValueFrom(this.providers$); const selected = await firstValueFrom(this.selected$); if (data == null) { return null; } if (selected != null && data.has(selected)) { return selected; } let providerType: TwoFactorProviderType = null; let providerPriority = -1; data.forEach((_value, type) => { const provider = (TwoFactorProviders as any)[type]; if (provider != null && provider.priority > providerPriority) { if (type === TwoFactorProviderType.WebAuthn && !webAuthnSupported) { return; } providerType = type; providerPriority = provider.priority; } }); return providerType; } async setSelectedProvider(type: TwoFactorProviderType): Promise { await this.selectedState.update(() => type); } async clearSelectedProvider(): Promise { await this.selectedState.update(() => null); } async setProviders(response: IdentityTwoFactorResponse): Promise { await this.providersState.update(() => response.twoFactorProviders2); } async clearProviders(): Promise { await this.providersState.update(() => null); } getProviders(): Promise | null> { return firstValueFrom(this.providers$); } getEnabledTwoFactorProviders(): Promise> { return this.twoFactorApiService.getTwoFactorProviders(); } getTwoFactorOrganizationProviders( organizationId: string, ): Promise> { return this.twoFactorApiService.getTwoFactorOrganizationProviders(organizationId); } getTwoFactorAuthenticator( request: SecretVerificationRequest, ): Promise { return this.twoFactorApiService.getTwoFactorAuthenticator(request); } getTwoFactorEmail(request: SecretVerificationRequest): Promise { return this.twoFactorApiService.getTwoFactorEmail(request); } getTwoFactorDuo(request: SecretVerificationRequest): Promise { return this.twoFactorApiService.getTwoFactorDuo(request); } getTwoFactorOrganizationDuo( organizationId: string, request: SecretVerificationRequest, ): Promise { return this.twoFactorApiService.getTwoFactorOrganizationDuo(organizationId, request); } getTwoFactorYubiKey(request: SecretVerificationRequest): Promise { return this.twoFactorApiService.getTwoFactorYubiKey(request); } getTwoFactorWebAuthn(request: SecretVerificationRequest): Promise { return this.twoFactorApiService.getTwoFactorWebAuthn(request); } getTwoFactorWebAuthnChallenge(request: SecretVerificationRequest): Promise { return this.twoFactorApiService.getTwoFactorWebAuthnChallenge(request); } getTwoFactorRecover(request: SecretVerificationRequest): Promise { return this.twoFactorApiService.getTwoFactorRecover(request); } putTwoFactorAuthenticator( request: UpdateTwoFactorAuthenticatorRequest, ): Promise { return this.twoFactorApiService.putTwoFactorAuthenticator(request); } deleteTwoFactorAuthenticator( request: DisableTwoFactorAuthenticatorRequest, ): Promise { return this.twoFactorApiService.deleteTwoFactorAuthenticator(request); } putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise { return this.twoFactorApiService.putTwoFactorEmail(request); } putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise { return this.twoFactorApiService.putTwoFactorDuo(request); } putTwoFactorOrganizationDuo( organizationId: string, request: UpdateTwoFactorDuoRequest, ): Promise { return this.twoFactorApiService.putTwoFactorOrganizationDuo(organizationId, request); } putTwoFactorYubiKey( request: UpdateTwoFactorYubikeyOtpRequest, ): Promise { return this.twoFactorApiService.putTwoFactorYubiKey(request); } putTwoFactorWebAuthn( request: UpdateTwoFactorWebAuthnRequest, ): Promise { return this.twoFactorApiService.putTwoFactorWebAuthn(request); } deleteTwoFactorWebAuthn( request: UpdateTwoFactorWebAuthnDeleteRequest, ): Promise { return this.twoFactorApiService.deleteTwoFactorWebAuthn(request); } putTwoFactorDisable(request: TwoFactorProviderRequest): Promise { return this.twoFactorApiService.putTwoFactorDisable(request); } putTwoFactorOrganizationDisable( organizationId: string, request: TwoFactorProviderRequest, ): Promise { return this.twoFactorApiService.putTwoFactorOrganizationDisable(organizationId, request); } postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise { return this.twoFactorApiService.postTwoFactorEmailSetup(request); } postTwoFactorEmail(request: TwoFactorEmailRequest): Promise { return this.twoFactorApiService.postTwoFactorEmail(request); } }