mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
Reapply feat(two-factor-api-service) [PM-26465]: (Refactor) Two-Factor API Service (#16856) (#16884)
This reverts commit d082d336e7.
Feature branch was accidentally merged before QA testing completed.
This commit is contained in:
@@ -14,7 +14,6 @@ import {
|
|||||||
SsoUrlService,
|
SsoUrlService,
|
||||||
UserApiLoginCredentials,
|
UserApiLoginCredentials,
|
||||||
} from "@bitwarden/auth/common";
|
} from "@bitwarden/auth/common";
|
||||||
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";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
@@ -29,6 +28,7 @@ import { TokenTwoFactorRequest } from "@bitwarden/common/auth/models/request/ide
|
|||||||
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";
|
||||||
import { UpdateTempPasswordRequest } from "@bitwarden/common/auth/models/request/update-temp-password.request";
|
import { UpdateTempPasswordRequest } from "@bitwarden/common/auth/models/request/update-temp-password.request";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { ClientType } from "@bitwarden/common/enums";
|
import { ClientType } from "@bitwarden/common/enums";
|
||||||
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
import { CryptoFunctionService } from "@bitwarden/common/key-management/crypto/abstractions/crypto-function.service";
|
||||||
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
import { EncString } from "@bitwarden/common/key-management/crypto/models/enc-string";
|
||||||
@@ -62,7 +62,7 @@ export class LoginCommand {
|
|||||||
constructor(
|
constructor(
|
||||||
protected loginStrategyService: LoginStrategyServiceAbstraction,
|
protected loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
protected authService: AuthService,
|
protected authService: AuthService,
|
||||||
protected apiService: ApiService,
|
protected twoFactorApiService: TwoFactorApiService,
|
||||||
protected masterPasswordApiService: MasterPasswordApiService,
|
protected masterPasswordApiService: MasterPasswordApiService,
|
||||||
protected cryptoFunctionService: CryptoFunctionService,
|
protected cryptoFunctionService: CryptoFunctionService,
|
||||||
protected environmentService: EnvironmentService,
|
protected environmentService: EnvironmentService,
|
||||||
@@ -279,7 +279,7 @@ export class LoginCommand {
|
|||||||
const emailReq = new TwoFactorEmailRequest();
|
const emailReq = new TwoFactorEmailRequest();
|
||||||
emailReq.email = await this.loginStrategyService.getEmail();
|
emailReq.email = await this.loginStrategyService.getEmail();
|
||||||
emailReq.masterPasswordHash = await this.loginStrategyService.getMasterPasswordHash();
|
emailReq.masterPasswordHash = await this.loginStrategyService.getMasterPasswordHash();
|
||||||
await this.apiService.postTwoFactorEmail(emailReq);
|
await this.twoFactorApiService.postTwoFactorEmail(emailReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (twoFactorToken == null) {
|
if (twoFactorToken == null) {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export class Program extends BaseProgram {
|
|||||||
const command = new LoginCommand(
|
const command = new LoginCommand(
|
||||||
this.serviceContainer.loginStrategyService,
|
this.serviceContainer.loginStrategyService,
|
||||||
this.serviceContainer.authService,
|
this.serviceContainer.authService,
|
||||||
this.serviceContainer.apiService,
|
this.serviceContainer.twoFactorApiService,
|
||||||
this.serviceContainer.masterPasswordApiService,
|
this.serviceContainer.masterPasswordApiService,
|
||||||
this.serviceContainer.cryptoFunctionService,
|
this.serviceContainer.cryptoFunctionService,
|
||||||
this.serviceContainer.environmentService,
|
this.serviceContainer.environmentService,
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import { TokenService } from "@bitwarden/common/auth/services/token.service";
|
|||||||
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
|
import { TwoFactorService } from "@bitwarden/common/auth/services/two-factor.service";
|
||||||
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
|
import { UserVerificationApiService } from "@bitwarden/common/auth/services/user-verification/user-verification-api.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
|
import { UserVerificationService } from "@bitwarden/common/auth/services/user-verification/user-verification.service";
|
||||||
|
import { TwoFactorApiService, DefaultTwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import {
|
import {
|
||||||
AutofillSettingsService,
|
AutofillSettingsService,
|
||||||
AutofillSettingsServiceAbstraction,
|
AutofillSettingsServiceAbstraction,
|
||||||
@@ -228,6 +229,7 @@ export class ServiceContainer {
|
|||||||
tokenService: TokenService;
|
tokenService: TokenService;
|
||||||
appIdService: AppIdService;
|
appIdService: AppIdService;
|
||||||
apiService: NodeApiService;
|
apiService: NodeApiService;
|
||||||
|
twoFactorApiService: TwoFactorApiService;
|
||||||
hibpApiService: HibpApiService;
|
hibpApiService: HibpApiService;
|
||||||
environmentService: EnvironmentService;
|
environmentService: EnvironmentService;
|
||||||
cipherService: CipherService;
|
cipherService: CipherService;
|
||||||
@@ -528,6 +530,8 @@ export class ServiceContainer {
|
|||||||
|
|
||||||
this.configApiService = new ConfigApiService(this.apiService);
|
this.configApiService = new ConfigApiService(this.apiService);
|
||||||
|
|
||||||
|
this.twoFactorApiService = new DefaultTwoFactorApiService(this.apiService);
|
||||||
|
|
||||||
this.authService = new AuthService(
|
this.authService = new AuthService(
|
||||||
this.accountService,
|
this.accountService,
|
||||||
this.messagingService,
|
this.messagingService,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { concatMap, takeUntil, map, lastValueFrom, firstValueFrom } from "rxjs";
|
import { concatMap, takeUntil, map, lastValueFrom, firstValueFrom } from "rxjs";
|
||||||
import { first, tap } from "rxjs/operators";
|
import { first, tap } from "rxjs/operators";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import {
|
import {
|
||||||
getOrganizationById,
|
getOrganizationById,
|
||||||
OrganizationService,
|
OrganizationService,
|
||||||
@@ -15,6 +14,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
|
|||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
@@ -35,7 +35,7 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent impleme
|
|||||||
tabbedHeader = false;
|
tabbedHeader = false;
|
||||||
constructor(
|
constructor(
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
apiService: ApiService,
|
twoFactorApiService: TwoFactorApiService,
|
||||||
messagingService: MessagingService,
|
messagingService: MessagingService,
|
||||||
policyService: PolicyService,
|
policyService: PolicyService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@@ -47,7 +47,7 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent impleme
|
|||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
dialogService,
|
dialogService,
|
||||||
apiService,
|
twoFactorApiService,
|
||||||
messagingService,
|
messagingService,
|
||||||
policyService,
|
policyService,
|
||||||
billingAccountProfileStateService,
|
billingAccountProfileStateService,
|
||||||
@@ -116,7 +116,7 @@ export class TwoFactorSetupComponent extends BaseTwoFactorSetupComponent impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getTwoFactorProviders() {
|
protected getTwoFactorProviders() {
|
||||||
return this.apiService.getTwoFactorOrganizationProviders(this.organizationId);
|
return this.twoFactorApiService.getTwoFactorOrganizationProviders(this.organizationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected filterProvider(type: TwoFactorProviderType): boolean {
|
protected filterProvider(type: TwoFactorProviderType): boolean {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { TwoFactorProviderResponse } from "@bitwarden/common/auth/models/response/two-factor-provider.response";
|
import { TwoFactorProviderResponse } from "@bitwarden/common/auth/models/response/two-factor-provider.response";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
@@ -22,12 +23,14 @@ describe("ChangeEmailComponent", () => {
|
|||||||
let fixture: ComponentFixture<ChangeEmailComponent>;
|
let fixture: ComponentFixture<ChangeEmailComponent>;
|
||||||
|
|
||||||
let apiService: MockProxy<ApiService>;
|
let apiService: MockProxy<ApiService>;
|
||||||
|
let twoFactorApiService: MockProxy<TwoFactorApiService>;
|
||||||
let accountService: FakeAccountService;
|
let accountService: FakeAccountService;
|
||||||
let keyService: MockProxy<KeyService>;
|
let keyService: MockProxy<KeyService>;
|
||||||
let kdfConfigService: MockProxy<KdfConfigService>;
|
let kdfConfigService: MockProxy<KdfConfigService>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
apiService = mock<ApiService>();
|
apiService = mock<ApiService>();
|
||||||
|
twoFactorApiService = mock<TwoFactorApiService>();
|
||||||
keyService = mock<KeyService>();
|
keyService = mock<KeyService>();
|
||||||
kdfConfigService = mock<KdfConfigService>();
|
kdfConfigService = mock<KdfConfigService>();
|
||||||
accountService = mockAccountServiceWith("UserId" as UserId);
|
accountService = mockAccountServiceWith("UserId" as UserId);
|
||||||
@@ -37,6 +40,7 @@ describe("ChangeEmailComponent", () => {
|
|||||||
providers: [
|
providers: [
|
||||||
{ provide: AccountService, useValue: accountService },
|
{ provide: AccountService, useValue: accountService },
|
||||||
{ provide: ApiService, useValue: apiService },
|
{ provide: ApiService, useValue: apiService },
|
||||||
|
{ provide: TwoFactorApiService, useValue: twoFactorApiService },
|
||||||
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
{ provide: I18nService, useValue: { t: (key: string) => key } },
|
||||||
{ provide: KeyService, useValue: keyService },
|
{ provide: KeyService, useValue: keyService },
|
||||||
{ provide: MessagingService, useValue: mock<MessagingService>() },
|
{ provide: MessagingService, useValue: mock<MessagingService>() },
|
||||||
@@ -57,7 +61,7 @@ describe("ChangeEmailComponent", () => {
|
|||||||
|
|
||||||
describe("ngOnInit", () => {
|
describe("ngOnInit", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
apiService.getTwoFactorProviders.mockResolvedValue({
|
twoFactorApiService.getTwoFactorProviders.mockResolvedValue({
|
||||||
data: [{ type: TwoFactorProviderType.Email, enabled: true } as TwoFactorProviderResponse],
|
data: [{ type: TwoFactorProviderType.Email, enabled: true } as TwoFactorProviderResponse],
|
||||||
} as ListResponse<TwoFactorProviderResponse>);
|
} as ListResponse<TwoFactorProviderResponse>);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-p
|
|||||||
import { EmailTokenRequest } from "@bitwarden/common/auth/models/request/email-token.request";
|
import { EmailTokenRequest } from "@bitwarden/common/auth/models/request/email-token.request";
|
||||||
import { EmailRequest } from "@bitwarden/common/auth/models/request/email.request";
|
import { EmailRequest } from "@bitwarden/common/auth/models/request/email.request";
|
||||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { UserId } from "@bitwarden/common/types/guid";
|
import { UserId } from "@bitwarden/common/types/guid";
|
||||||
@@ -37,6 +38,7 @@ export class ChangeEmailComponent implements OnInit {
|
|||||||
constructor(
|
constructor(
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
|
private twoFactorApiService: TwoFactorApiService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private keyService: KeyService,
|
private keyService: KeyService,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
@@ -48,7 +50,7 @@ export class ChangeEmailComponent implements OnInit {
|
|||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
this.userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||||
|
|
||||||
const twoFactorProviders = await this.apiService.getTwoFactorProviders();
|
const twoFactorProviders = await this.twoFactorApiService.getTwoFactorProviders();
|
||||||
this.showTwoFactorEmailWarning = twoFactorProviders.data.some(
|
this.showTwoFactorEmailWarning = twoFactorProviders.data.some(
|
||||||
(p) => p.type === TwoFactorProviderType.Email && p.enabled,
|
(p) => p.type === TwoFactorProviderType.Email && p.enabled,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import { firstValueFrom, Subject, takeUntil } from "rxjs";
|
|||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { UserVerificationFormInputComponent } from "@bitwarden/auth/angular";
|
import { UserVerificationFormInputComponent } from "@bitwarden/auth/angular";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service";
|
import { AccountApiService } from "@bitwarden/common/auth/abstractions/account-api.service";
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { SetVerifyDevicesRequest } from "@bitwarden/common/auth/models/request/set-verify-devices.request";
|
import { SetVerifyDevicesRequest } from "@bitwarden/common/auth/models/request/set-verify-devices.request";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { Verification } from "@bitwarden/common/auth/types/verification";
|
import { Verification } from "@bitwarden/common/auth/types/verification";
|
||||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -64,7 +64,7 @@ export class SetAccountVerifyDevicesDialogComponent implements OnInit, OnDestroy
|
|||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
private dialogRef: DialogRef,
|
private dialogRef: DialogRef,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private apiService: ApiService,
|
private twoFactorApiService: TwoFactorApiService,
|
||||||
) {
|
) {
|
||||||
this.accountService.accountVerifyNewDeviceLogin$
|
this.accountService.accountVerifyNewDeviceLogin$
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
@@ -74,7 +74,7 @@ export class SetAccountVerifyDevicesDialogComponent implements OnInit, OnDestroy
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
const twoFactorProviders = await this.apiService.getTwoFactorProviders();
|
const twoFactorProviders = await this.twoFactorApiService.getTwoFactorProviders();
|
||||||
this.has2faConfigured = twoFactorProviders.data.length > 0;
|
this.has2faConfigured = twoFactorProviders.data.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { FormBuilder, FormControl, ReactiveFormsModule, Validators } from "@angu
|
|||||||
import { firstValueFrom, map } from "rxjs";
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { DisableTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/disable-two-factor-authenticator.request";
|
import { DisableTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/disable-two-factor-authenticator.request";
|
||||||
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/update-two-factor-authenticator.request";
|
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/update-two-factor-authenticator.request";
|
||||||
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/auth/models/response/two-factor-authenticator.response";
|
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/auth/models/response/two-factor-authenticator.response";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -92,7 +92,7 @@ export class TwoFactorSetupAuthenticatorComponent
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorAuthenticatorResponse>,
|
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorAuthenticatorResponse>,
|
||||||
private dialogRef: DialogRef,
|
private dialogRef: DialogRef,
|
||||||
apiService: ApiService,
|
twoFactorApiService: TwoFactorApiService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
userVerificationService: UserVerificationService,
|
userVerificationService: UserVerificationService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
@@ -104,7 +104,7 @@ export class TwoFactorSetupAuthenticatorComponent
|
|||||||
protected toastService: ToastService,
|
protected toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
apiService,
|
twoFactorApiService,
|
||||||
i18nService,
|
i18nService,
|
||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
logService,
|
logService,
|
||||||
@@ -154,7 +154,7 @@ export class TwoFactorSetupAuthenticatorComponent
|
|||||||
request.key = this.key;
|
request.key = this.key;
|
||||||
request.userVerificationToken = this.userVerificationToken;
|
request.userVerificationToken = this.userVerificationToken;
|
||||||
|
|
||||||
const response = await this.apiService.putTwoFactorAuthenticator(request);
|
const response = await this.twoFactorApiService.putTwoFactorAuthenticator(request);
|
||||||
await this.processResponse(response);
|
await this.processResponse(response);
|
||||||
this.onUpdated.emit(true);
|
this.onUpdated.emit(true);
|
||||||
}
|
}
|
||||||
@@ -174,7 +174,7 @@ export class TwoFactorSetupAuthenticatorComponent
|
|||||||
request.type = this.type;
|
request.type = this.type;
|
||||||
request.key = this.key;
|
request.key = this.key;
|
||||||
request.userVerificationToken = this.userVerificationToken;
|
request.userVerificationToken = this.userVerificationToken;
|
||||||
await this.apiService.deleteTwoFactorAuthenticator(request);
|
await this.twoFactorApiService.deleteTwoFactorAuthenticator(request);
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
variant: "success",
|
variant: "success",
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { CommonModule } from "@angular/common";
|
|||||||
import { Component, EventEmitter, Inject, OnInit, Output } from "@angular/core";
|
import { Component, EventEmitter, Inject, OnInit, Output } from "@angular/core";
|
||||||
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/auth/models/request/update-two-factor-duo.request";
|
import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/auth/models/request/update-two-factor-duo.request";
|
||||||
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -63,7 +63,7 @@ export class TwoFactorSetupDuoComponent
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) protected data: TwoFactorDuoComponentConfig,
|
@Inject(DIALOG_DATA) protected data: TwoFactorDuoComponentConfig,
|
||||||
apiService: ApiService,
|
twoFactorApiService: TwoFactorApiService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
@@ -74,7 +74,7 @@ export class TwoFactorSetupDuoComponent
|
|||||||
protected toastService: ToastService,
|
protected toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
apiService,
|
twoFactorApiService,
|
||||||
i18nService,
|
i18nService,
|
||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
logService,
|
logService,
|
||||||
@@ -139,9 +139,12 @@ export class TwoFactorSetupDuoComponent
|
|||||||
let response: TwoFactorDuoResponse;
|
let response: TwoFactorDuoResponse;
|
||||||
|
|
||||||
if (this.organizationId != null) {
|
if (this.organizationId != null) {
|
||||||
response = await this.apiService.putTwoFactorOrganizationDuo(this.organizationId, request);
|
response = await this.twoFactorApiService.putTwoFactorOrganizationDuo(
|
||||||
|
this.organizationId,
|
||||||
|
request,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
response = await this.apiService.putTwoFactorDuo(request);
|
response = await this.twoFactorApiService.putTwoFactorDuo(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ import { Component, EventEmitter, Inject, OnInit, Output } from "@angular/core";
|
|||||||
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
import { firstValueFrom, map } from "rxjs";
|
import { firstValueFrom, map } from "rxjs";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
||||||
import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/update-two-factor-email.request";
|
import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/update-two-factor-email.request";
|
||||||
import { TwoFactorEmailResponse } from "@bitwarden/common/auth/models/response/two-factor-email.response";
|
import { TwoFactorEmailResponse } from "@bitwarden/common/auth/models/response/two-factor-email.response";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -66,7 +66,7 @@ export class TwoFactorSetupEmailComponent
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorEmailResponse>,
|
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorEmailResponse>,
|
||||||
apiService: ApiService,
|
twoFactorApiService: TwoFactorApiService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
@@ -78,7 +78,7 @@ export class TwoFactorSetupEmailComponent
|
|||||||
protected toastService: ToastService,
|
protected toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
apiService,
|
twoFactorApiService,
|
||||||
i18nService,
|
i18nService,
|
||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
logService,
|
logService,
|
||||||
@@ -131,7 +131,7 @@ export class TwoFactorSetupEmailComponent
|
|||||||
sendEmail = async () => {
|
sendEmail = async () => {
|
||||||
const request = await this.buildRequestModel(TwoFactorEmailRequest);
|
const request = await this.buildRequestModel(TwoFactorEmailRequest);
|
||||||
request.email = this.email;
|
request.email = this.email;
|
||||||
this.emailPromise = this.apiService.postTwoFactorEmailSetup(request);
|
this.emailPromise = this.twoFactorApiService.postTwoFactorEmailSetup(request);
|
||||||
await this.emailPromise;
|
await this.emailPromise;
|
||||||
this.sentEmail = this.email;
|
this.sentEmail = this.email;
|
||||||
};
|
};
|
||||||
@@ -141,7 +141,7 @@ export class TwoFactorSetupEmailComponent
|
|||||||
request.email = this.email;
|
request.email = this.email;
|
||||||
request.token = this.token;
|
request.token = this.token;
|
||||||
|
|
||||||
const response = await this.apiService.putTwoFactorEmail(request);
|
const response = await this.twoFactorApiService.putTwoFactorEmail(request);
|
||||||
await this.processResponse(response);
|
await this.processResponse(response);
|
||||||
this.onUpdated.emit(true);
|
this.onUpdated.emit(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Directive, EventEmitter, Output } from "@angular/core";
|
import { Directive, EventEmitter, Output } from "@angular/core";
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
||||||
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
||||||
import { TwoFactorProviderRequest } from "@bitwarden/common/auth/models/request/two-factor-provider.request";
|
import { TwoFactorProviderRequest } from "@bitwarden/common/auth/models/request/two-factor-provider.request";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponseBase } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponseBase } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -30,7 +30,7 @@ export abstract class TwoFactorSetupMethodBaseComponent {
|
|||||||
protected componentName = "";
|
protected componentName = "";
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected apiService: ApiService,
|
protected twoFactorApiService: TwoFactorApiService,
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
protected logService: LogService,
|
protected logService: LogService,
|
||||||
@@ -77,9 +77,12 @@ export abstract class TwoFactorSetupMethodBaseComponent {
|
|||||||
}
|
}
|
||||||
request.type = this.type;
|
request.type = this.type;
|
||||||
if (this.organizationId != null) {
|
if (this.organizationId != null) {
|
||||||
promise = this.apiService.putTwoFactorOrganizationDisable(this.organizationId, request);
|
promise = this.twoFactorApiService.putTwoFactorOrganizationDisable(
|
||||||
|
this.organizationId,
|
||||||
|
request,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
promise = this.apiService.putTwoFactorDisable(request);
|
promise = this.twoFactorApiService.putTwoFactorDisable(request);
|
||||||
}
|
}
|
||||||
await promise;
|
await promise;
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
@@ -111,9 +114,9 @@ export abstract class TwoFactorSetupMethodBaseComponent {
|
|||||||
}
|
}
|
||||||
request.type = this.type;
|
request.type = this.type;
|
||||||
if (this.organizationId != null) {
|
if (this.organizationId != null) {
|
||||||
await this.apiService.putTwoFactorOrganizationDisable(this.organizationId, request);
|
await this.twoFactorApiService.putTwoFactorOrganizationDisable(this.organizationId, request);
|
||||||
} else {
|
} else {
|
||||||
await this.apiService.putTwoFactorDisable(request);
|
await this.twoFactorApiService.putTwoFactorDisable(request);
|
||||||
}
|
}
|
||||||
this.enabled = false;
|
this.enabled = false;
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Component, Inject, NgZone } from "@angular/core";
|
|||||||
import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
|
import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
||||||
@@ -13,6 +12,7 @@ import {
|
|||||||
ChallengeResponse,
|
ChallengeResponse,
|
||||||
TwoFactorWebAuthnResponse,
|
TwoFactorWebAuthnResponse,
|
||||||
} from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
} from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -79,7 +79,7 @@ export class TwoFactorSetupWebAuthnComponent extends TwoFactorSetupMethodBaseCom
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorWebAuthnResponse>,
|
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorWebAuthnResponse>,
|
||||||
private dialogRef: DialogRef,
|
private dialogRef: DialogRef,
|
||||||
apiService: ApiService,
|
twoFactorApiService: TwoFactorApiService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
private ngZone: NgZone,
|
private ngZone: NgZone,
|
||||||
@@ -89,7 +89,7 @@ export class TwoFactorSetupWebAuthnComponent extends TwoFactorSetupMethodBaseCom
|
|||||||
toastService: ToastService,
|
toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
apiService,
|
twoFactorApiService,
|
||||||
i18nService,
|
i18nService,
|
||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
logService,
|
logService,
|
||||||
@@ -127,7 +127,7 @@ export class TwoFactorSetupWebAuthnComponent extends TwoFactorSetupMethodBaseCom
|
|||||||
request.id = this.keyIdAvailable;
|
request.id = this.keyIdAvailable;
|
||||||
request.name = this.formGroup.value.name || "";
|
request.name = this.formGroup.value.name || "";
|
||||||
|
|
||||||
const response = await this.apiService.putTwoFactorWebAuthn(request);
|
const response = await this.twoFactorApiService.putTwoFactorWebAuthn(request);
|
||||||
this.processResponse(response);
|
this.processResponse(response);
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
title: this.i18nService.t("success"),
|
title: this.i18nService.t("success"),
|
||||||
@@ -163,7 +163,7 @@ export class TwoFactorSetupWebAuthnComponent extends TwoFactorSetupMethodBaseCom
|
|||||||
const request = await this.buildRequestModel(UpdateTwoFactorWebAuthnDeleteRequest);
|
const request = await this.buildRequestModel(UpdateTwoFactorWebAuthnDeleteRequest);
|
||||||
request.id = key.id;
|
request.id = key.id;
|
||||||
try {
|
try {
|
||||||
key.removePromise = this.apiService.deleteTwoFactorWebAuthn(request);
|
key.removePromise = this.twoFactorApiService.deleteTwoFactorWebAuthn(request);
|
||||||
const response = await key.removePromise;
|
const response = await key.removePromise;
|
||||||
key.removePromise = null;
|
key.removePromise = null;
|
||||||
await this.processResponse(response);
|
await this.processResponse(response);
|
||||||
@@ -177,7 +177,7 @@ export class TwoFactorSetupWebAuthnComponent extends TwoFactorSetupMethodBaseCom
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const request = await this.buildRequestModel(SecretVerificationRequest);
|
const request = await this.buildRequestModel(SecretVerificationRequest);
|
||||||
this.challengePromise = this.apiService.getTwoFactorWebAuthnChallenge(request);
|
this.challengePromise = this.twoFactorApiService.getTwoFactorWebAuthnChallenge(request);
|
||||||
const challenge = await this.challengePromise;
|
const challenge = await this.challengePromise;
|
||||||
this.readDevice(challenge);
|
this.readDevice(challenge);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import {
|
|||||||
} from "@angular/forms";
|
} from "@angular/forms";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { UpdateTwoFactorYubikeyOtpRequest } from "@bitwarden/common/auth/models/request/update-two-factor-yubikey-otp.request";
|
import { UpdateTwoFactorYubikeyOtpRequest } from "@bitwarden/common/auth/models/request/update-two-factor-yubikey-otp.request";
|
||||||
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -93,7 +93,7 @@ export class TwoFactorSetupYubiKeyComponent
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorYubiKeyResponse>,
|
@Inject(DIALOG_DATA) protected data: AuthResponse<TwoFactorYubiKeyResponse>,
|
||||||
apiService: ApiService,
|
twoFactorApiService: TwoFactorApiService,
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
platformUtilsService: PlatformUtilsService,
|
platformUtilsService: PlatformUtilsService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
@@ -103,7 +103,7 @@ export class TwoFactorSetupYubiKeyComponent
|
|||||||
protected toastService: ToastService,
|
protected toastService: ToastService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
apiService,
|
twoFactorApiService,
|
||||||
i18nService,
|
i18nService,
|
||||||
platformUtilsService,
|
platformUtilsService,
|
||||||
logService,
|
logService,
|
||||||
@@ -176,7 +176,7 @@ export class TwoFactorSetupYubiKeyComponent
|
|||||||
request.key5 = keys != null && keys.length > 4 ? (keys[4]?.key ?? "") : "";
|
request.key5 = keys != null && keys.length > 4 ? (keys[4]?.key ?? "") : "";
|
||||||
request.nfc = this.formGroup.value.anyKeyHasNfc ?? false;
|
request.nfc = this.formGroup.value.anyKeyHasNfc ?? false;
|
||||||
|
|
||||||
this.processResponse(await this.apiService.putTwoFactorYubiKey(request));
|
this.processResponse(await this.twoFactorApiService.putTwoFactorYubiKey(request));
|
||||||
this.refreshFormArrayData();
|
this.refreshFormArrayData();
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
title: this.i18nService.t("success"),
|
title: this.i18nService.t("success"),
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
} from "rxjs";
|
} from "rxjs";
|
||||||
|
|
||||||
import { PremiumBadgeComponent } from "@bitwarden/angular/billing/components/premium-badge";
|
import { PremiumBadgeComponent } from "@bitwarden/angular/billing/components/premium-badge";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
@@ -26,6 +25,7 @@ import { TwoFactorWebAuthnResponse } from "@bitwarden/common/auth/models/respons
|
|||||||
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
||||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||||
import { TwoFactorProviders } from "@bitwarden/common/auth/services/two-factor.service";
|
import { TwoFactorProviders } from "@bitwarden/common/auth/services/two-factor.service";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||||
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||||
@@ -68,7 +68,7 @@ export class TwoFactorSetupComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected dialogService: DialogService,
|
protected dialogService: DialogService,
|
||||||
protected apiService: ApiService,
|
protected twoFactorApiService: TwoFactorApiService,
|
||||||
protected messagingService: MessagingService,
|
protected messagingService: MessagingService,
|
||||||
protected policyService: PolicyService,
|
protected policyService: PolicyService,
|
||||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
@@ -270,7 +270,7 @@ export class TwoFactorSetupComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected getTwoFactorProviders() {
|
protected getTwoFactorProviders() {
|
||||||
return this.apiService.getTwoFactorProviders();
|
return this.twoFactorApiService.getTwoFactorProviders();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected filterProvider(type: TwoFactorProviderType): boolean {
|
protected filterProvider(type: TwoFactorProviderType): boolean {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { Component, EventEmitter, Inject, Output } from "@angular/core";
|
|||||||
import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
|
import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";
|
||||||
|
|
||||||
import { UserVerificationFormInputComponent } from "@bitwarden/auth/angular";
|
import { UserVerificationFormInputComponent } from "@bitwarden/auth/angular";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||||
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
import { TwoFactorProviderType } from "@bitwarden/common/auth/enums/two-factor-provider-type";
|
||||||
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
import { VerificationType } from "@bitwarden/common/auth/enums/verification-type";
|
||||||
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
import { TwoFactorResponse } from "@bitwarden/common/auth/types/two-factor-response";
|
import { TwoFactorResponse } from "@bitwarden/common/auth/types/two-factor-response";
|
||||||
import { Verification } from "@bitwarden/common/auth/types/verification";
|
import { Verification } from "@bitwarden/common/auth/types/verification";
|
||||||
@@ -55,7 +55,7 @@ export class TwoFactorVerifyComponent {
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(DIALOG_DATA) protected data: TwoFactorVerifyDialogData,
|
@Inject(DIALOG_DATA) protected data: TwoFactorVerifyDialogData,
|
||||||
private dialogRef: DialogRef,
|
private dialogRef: DialogRef,
|
||||||
private apiService: ApiService,
|
private twoFactorApiService: TwoFactorApiService,
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private userVerificationService: UserVerificationService,
|
private userVerificationService: UserVerificationService,
|
||||||
) {
|
) {
|
||||||
@@ -116,22 +116,22 @@ export class TwoFactorVerifyComponent {
|
|||||||
private apiCall(request: SecretVerificationRequest): Promise<TwoFactorResponse> {
|
private apiCall(request: SecretVerificationRequest): Promise<TwoFactorResponse> {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case -1 as TwoFactorProviderType:
|
case -1 as TwoFactorProviderType:
|
||||||
return this.apiService.getTwoFactorRecover(request);
|
return this.twoFactorApiService.getTwoFactorRecover(request);
|
||||||
case TwoFactorProviderType.Duo:
|
case TwoFactorProviderType.Duo:
|
||||||
case TwoFactorProviderType.OrganizationDuo:
|
case TwoFactorProviderType.OrganizationDuo:
|
||||||
if (this.organizationId != null) {
|
if (this.organizationId != null) {
|
||||||
return this.apiService.getTwoFactorOrganizationDuo(this.organizationId, request);
|
return this.twoFactorApiService.getTwoFactorOrganizationDuo(this.organizationId, request);
|
||||||
} else {
|
} else {
|
||||||
return this.apiService.getTwoFactorDuo(request);
|
return this.twoFactorApiService.getTwoFactorDuo(request);
|
||||||
}
|
}
|
||||||
case TwoFactorProviderType.Email:
|
case TwoFactorProviderType.Email:
|
||||||
return this.apiService.getTwoFactorEmail(request);
|
return this.twoFactorApiService.getTwoFactorEmail(request);
|
||||||
case TwoFactorProviderType.WebAuthn:
|
case TwoFactorProviderType.WebAuthn:
|
||||||
return this.apiService.getTwoFactorWebAuthn(request);
|
return this.twoFactorApiService.getTwoFactorWebAuthn(request);
|
||||||
case TwoFactorProviderType.Authenticator:
|
case TwoFactorProviderType.Authenticator:
|
||||||
return this.apiService.getTwoFactorAuthenticator(request);
|
return this.twoFactorApiService.getTwoFactorAuthenticator(request);
|
||||||
case TwoFactorProviderType.Yubikey:
|
case TwoFactorProviderType.Yubikey:
|
||||||
return this.apiService.getTwoFactorYubiKey(request);
|
return this.twoFactorApiService.getTwoFactorYubiKey(request);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown two-factor type: ${this.type}`);
|
throw new Error(`Unknown two-factor type: ${this.type}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ import { UserVerificationService } from "@bitwarden/common/auth/services/user-ve
|
|||||||
import { WebAuthnLoginApiService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login-api.service";
|
import { WebAuthnLoginApiService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login-api.service";
|
||||||
import { WebAuthnLoginPrfKeyService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login-prf-key.service";
|
import { WebAuthnLoginPrfKeyService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login-prf-key.service";
|
||||||
import { WebAuthnLoginService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login.service";
|
import { WebAuthnLoginService } from "@bitwarden/common/auth/services/webauthn-login/webauthn-login.service";
|
||||||
|
import { TwoFactorApiService, DefaultTwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import {
|
import {
|
||||||
AutofillSettingsService,
|
AutofillSettingsService,
|
||||||
AutofillSettingsServiceAbstraction,
|
AutofillSettingsServiceAbstraction,
|
||||||
@@ -1527,6 +1528,11 @@ const safeProviders: SafeProvider[] = [
|
|||||||
useClass: DefaultTwoFactorAuthWebAuthnComponentService,
|
useClass: DefaultTwoFactorAuthWebAuthnComponentService,
|
||||||
deps: [],
|
deps: [],
|
||||||
}),
|
}),
|
||||||
|
safeProvider({
|
||||||
|
provide: TwoFactorApiService,
|
||||||
|
useClass: DefaultTwoFactorApiService,
|
||||||
|
deps: [ApiServiceAbstraction],
|
||||||
|
}),
|
||||||
safeProvider({
|
safeProvider({
|
||||||
provide: ViewCacheService,
|
provide: ViewCacheService,
|
||||||
useExisting: NoopViewCacheService,
|
useExisting: NoopViewCacheService,
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { ReactiveFormsModule, FormsModule, FormControl } from "@angular/forms";
|
|||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
import { LoginStrategyServiceAbstraction } from "@bitwarden/auth/common";
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.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";
|
||||||
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
||||||
|
import { TwoFactorApiService } from "@bitwarden/common/auth/two-factor";
|
||||||
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
import { AppIdService } from "@bitwarden/common/platform/abstractions/app-id.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@@ -62,7 +62,7 @@ export class TwoFactorAuthEmailComponent implements OnInit {
|
|||||||
protected loginStrategyService: LoginStrategyServiceAbstraction,
|
protected loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
protected logService: LogService,
|
protected logService: LogService,
|
||||||
protected apiService: ApiService,
|
protected twoFactorApiService: TwoFactorApiService,
|
||||||
protected appIdService: AppIdService,
|
protected appIdService: AppIdService,
|
||||||
private toastService: ToastService,
|
private toastService: ToastService,
|
||||||
private cacheService: TwoFactorAuthEmailComponentCacheService,
|
private cacheService: TwoFactorAuthEmailComponentCacheService,
|
||||||
@@ -131,7 +131,7 @@ export class TwoFactorAuthEmailComponent implements OnInit {
|
|||||||
request.deviceIdentifier = await this.appIdService.getAppId();
|
request.deviceIdentifier = await this.appIdService.getAppId();
|
||||||
request.authRequestAccessCode = (await this.loginStrategyService.getAccessCode()) ?? "";
|
request.authRequestAccessCode = (await this.loginStrategyService.getAccessCode()) ?? "";
|
||||||
request.authRequestId = (await this.loginStrategyService.getAuthRequestId()) ?? "";
|
request.authRequestId = (await this.loginStrategyService.getAuthRequestId()) ?? "";
|
||||||
this.emailPromise = this.apiService.postTwoFactorEmail(request);
|
this.emailPromise = this.twoFactorApiService.postTwoFactorEmail(request);
|
||||||
await this.emailPromise;
|
await this.emailPromise;
|
||||||
|
|
||||||
this.emailSent = true;
|
this.emailSent = true;
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ import {
|
|||||||
ProviderUserUserDetailsResponse,
|
ProviderUserUserDetailsResponse,
|
||||||
} from "../admin-console/models/response/provider/provider-user.response";
|
} from "../admin-console/models/response/provider/provider-user.response";
|
||||||
import { SelectionReadOnlyResponse } from "../admin-console/models/response/selection-read-only.response";
|
import { SelectionReadOnlyResponse } from "../admin-console/models/response/selection-read-only.response";
|
||||||
import { DeviceVerificationRequest } from "../auth/models/request/device-verification.request";
|
|
||||||
import { DisableTwoFactorAuthenticatorRequest } from "../auth/models/request/disable-two-factor-authenticator.request";
|
|
||||||
import { EmailTokenRequest } from "../auth/models/request/email-token.request";
|
import { EmailTokenRequest } from "../auth/models/request/email-token.request";
|
||||||
import { EmailRequest } from "../auth/models/request/email.request";
|
import { EmailRequest } from "../auth/models/request/email.request";
|
||||||
import { PasswordTokenRequest } from "../auth/models/request/identity-token/password-token.request";
|
import { PasswordTokenRequest } from "../auth/models/request/identity-token/password-token.request";
|
||||||
@@ -48,34 +46,15 @@ import { WebAuthnLoginTokenRequest } from "../auth/models/request/identity-token
|
|||||||
import { PasswordHintRequest } from "../auth/models/request/password-hint.request";
|
import { PasswordHintRequest } from "../auth/models/request/password-hint.request";
|
||||||
import { PasswordlessAuthRequest } from "../auth/models/request/passwordless-auth.request";
|
import { PasswordlessAuthRequest } from "../auth/models/request/passwordless-auth.request";
|
||||||
import { SecretVerificationRequest } from "../auth/models/request/secret-verification.request";
|
import { SecretVerificationRequest } from "../auth/models/request/secret-verification.request";
|
||||||
import { TwoFactorEmailRequest } from "../auth/models/request/two-factor-email.request";
|
|
||||||
import { TwoFactorProviderRequest } from "../auth/models/request/two-factor-provider.request";
|
|
||||||
import { UpdateProfileRequest } from "../auth/models/request/update-profile.request";
|
import { UpdateProfileRequest } from "../auth/models/request/update-profile.request";
|
||||||
import { UpdateTwoFactorAuthenticatorRequest } from "../auth/models/request/update-two-factor-authenticator.request";
|
|
||||||
import { UpdateTwoFactorDuoRequest } from "../auth/models/request/update-two-factor-duo.request";
|
|
||||||
import { UpdateTwoFactorEmailRequest } from "../auth/models/request/update-two-factor-email.request";
|
|
||||||
import { UpdateTwoFactorWebAuthnDeleteRequest } from "../auth/models/request/update-two-factor-web-authn-delete.request";
|
|
||||||
import { UpdateTwoFactorWebAuthnRequest } from "../auth/models/request/update-two-factor-web-authn.request";
|
|
||||||
import { UpdateTwoFactorYubikeyOtpRequest } from "../auth/models/request/update-two-factor-yubikey-otp.request";
|
|
||||||
import { ApiKeyResponse } from "../auth/models/response/api-key.response";
|
import { ApiKeyResponse } from "../auth/models/response/api-key.response";
|
||||||
import { AuthRequestResponse } from "../auth/models/response/auth-request.response";
|
import { AuthRequestResponse } from "../auth/models/response/auth-request.response";
|
||||||
import { DeviceVerificationResponse } from "../auth/models/response/device-verification.response";
|
|
||||||
import { IdentityDeviceVerificationResponse } from "../auth/models/response/identity-device-verification.response";
|
import { IdentityDeviceVerificationResponse } from "../auth/models/response/identity-device-verification.response";
|
||||||
import { IdentityTokenResponse } from "../auth/models/response/identity-token.response";
|
import { IdentityTokenResponse } from "../auth/models/response/identity-token.response";
|
||||||
import { IdentityTwoFactorResponse } from "../auth/models/response/identity-two-factor.response";
|
import { IdentityTwoFactorResponse } from "../auth/models/response/identity-two-factor.response";
|
||||||
import { KeyConnectorUserKeyResponse } from "../auth/models/response/key-connector-user-key.response";
|
import { KeyConnectorUserKeyResponse } from "../auth/models/response/key-connector-user-key.response";
|
||||||
import { PreloginResponse } from "../auth/models/response/prelogin.response";
|
import { PreloginResponse } from "../auth/models/response/prelogin.response";
|
||||||
import { SsoPreValidateResponse } from "../auth/models/response/sso-pre-validate.response";
|
import { SsoPreValidateResponse } from "../auth/models/response/sso-pre-validate.response";
|
||||||
import { TwoFactorAuthenticatorResponse } from "../auth/models/response/two-factor-authenticator.response";
|
|
||||||
import { TwoFactorDuoResponse } from "../auth/models/response/two-factor-duo.response";
|
|
||||||
import { TwoFactorEmailResponse } from "../auth/models/response/two-factor-email.response";
|
|
||||||
import { TwoFactorProviderResponse } from "../auth/models/response/two-factor-provider.response";
|
|
||||||
import { TwoFactorRecoverResponse } from "../auth/models/response/two-factor-recover.response";
|
|
||||||
import {
|
|
||||||
ChallengeResponse,
|
|
||||||
TwoFactorWebAuthnResponse,
|
|
||||||
} from "../auth/models/response/two-factor-web-authn.response";
|
|
||||||
import { TwoFactorYubiKeyResponse } from "../auth/models/response/two-factor-yubi-key.response";
|
|
||||||
import { BitPayInvoiceRequest } from "../billing/models/request/bit-pay-invoice.request";
|
import { BitPayInvoiceRequest } from "../billing/models/request/bit-pay-invoice.request";
|
||||||
import { BillingHistoryResponse } from "../billing/models/response/billing-history.response";
|
import { BillingHistoryResponse } from "../billing/models/response/billing-history.response";
|
||||||
import { PaymentResponse } from "../billing/models/response/payment.response";
|
import { PaymentResponse } from "../billing/models/response/payment.response";
|
||||||
@@ -306,66 +285,6 @@ export abstract class ApiService {
|
|||||||
abstract getSettingsDomains(): Promise<DomainsResponse>;
|
abstract getSettingsDomains(): Promise<DomainsResponse>;
|
||||||
abstract putSettingsDomains(request: UpdateDomainsRequest): Promise<DomainsResponse>;
|
abstract putSettingsDomains(request: UpdateDomainsRequest): Promise<DomainsResponse>;
|
||||||
|
|
||||||
abstract getTwoFactorProviders(): Promise<ListResponse<TwoFactorProviderResponse>>;
|
|
||||||
abstract getTwoFactorOrganizationProviders(
|
|
||||||
organizationId: string,
|
|
||||||
): Promise<ListResponse<TwoFactorProviderResponse>>;
|
|
||||||
abstract getTwoFactorAuthenticator(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorAuthenticatorResponse>;
|
|
||||||
abstract getTwoFactorEmail(request: SecretVerificationRequest): Promise<TwoFactorEmailResponse>;
|
|
||||||
abstract getTwoFactorDuo(request: SecretVerificationRequest): Promise<TwoFactorDuoResponse>;
|
|
||||||
abstract getTwoFactorOrganizationDuo(
|
|
||||||
organizationId: string,
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorDuoResponse>;
|
|
||||||
abstract getTwoFactorYubiKey(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorYubiKeyResponse>;
|
|
||||||
abstract getTwoFactorWebAuthn(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorWebAuthnResponse>;
|
|
||||||
abstract getTwoFactorWebAuthnChallenge(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<ChallengeResponse>;
|
|
||||||
abstract getTwoFactorRecover(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorRecoverResponse>;
|
|
||||||
abstract putTwoFactorAuthenticator(
|
|
||||||
request: UpdateTwoFactorAuthenticatorRequest,
|
|
||||||
): Promise<TwoFactorAuthenticatorResponse>;
|
|
||||||
abstract deleteTwoFactorAuthenticator(
|
|
||||||
request: DisableTwoFactorAuthenticatorRequest,
|
|
||||||
): Promise<TwoFactorProviderResponse>;
|
|
||||||
abstract putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise<TwoFactorEmailResponse>;
|
|
||||||
abstract putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise<TwoFactorDuoResponse>;
|
|
||||||
abstract putTwoFactorOrganizationDuo(
|
|
||||||
organizationId: string,
|
|
||||||
request: UpdateTwoFactorDuoRequest,
|
|
||||||
): Promise<TwoFactorDuoResponse>;
|
|
||||||
abstract putTwoFactorYubiKey(
|
|
||||||
request: UpdateTwoFactorYubikeyOtpRequest,
|
|
||||||
): Promise<TwoFactorYubiKeyResponse>;
|
|
||||||
abstract putTwoFactorWebAuthn(
|
|
||||||
request: UpdateTwoFactorWebAuthnRequest,
|
|
||||||
): Promise<TwoFactorWebAuthnResponse>;
|
|
||||||
abstract deleteTwoFactorWebAuthn(
|
|
||||||
request: UpdateTwoFactorWebAuthnDeleteRequest,
|
|
||||||
): Promise<TwoFactorWebAuthnResponse>;
|
|
||||||
abstract putTwoFactorDisable(
|
|
||||||
request: TwoFactorProviderRequest,
|
|
||||||
): Promise<TwoFactorProviderResponse>;
|
|
||||||
abstract putTwoFactorOrganizationDisable(
|
|
||||||
organizationId: string,
|
|
||||||
request: TwoFactorProviderRequest,
|
|
||||||
): Promise<TwoFactorProviderResponse>;
|
|
||||||
abstract postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise<any>;
|
|
||||||
abstract postTwoFactorEmail(request: TwoFactorEmailRequest): Promise<any>;
|
|
||||||
abstract getDeviceVerificationSettings(): Promise<DeviceVerificationResponse>;
|
|
||||||
abstract putDeviceVerificationSettings(
|
|
||||||
request: DeviceVerificationRequest,
|
|
||||||
): Promise<DeviceVerificationResponse>;
|
|
||||||
|
|
||||||
abstract getCloudCommunicationsEnabled(): Promise<boolean>;
|
abstract getCloudCommunicationsEnabled(): Promise<boolean>;
|
||||||
abstract getOrganizationConnection<TConfig extends OrganizationConnectionConfigApis>(
|
abstract getOrganizationConnection<TConfig extends OrganizationConnectionConfigApis>(
|
||||||
id: string,
|
id: string,
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
export class DeviceVerificationRequest {
|
|
||||||
unknownDeviceVerificationEnabled: boolean;
|
|
||||||
|
|
||||||
constructor(unknownDeviceVerificationEnabled: boolean) {
|
|
||||||
this.unknownDeviceVerificationEnabled = unknownDeviceVerificationEnabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { BaseResponse } from "../../../models/response/base.response";
|
|
||||||
|
|
||||||
export class DeviceVerificationResponse extends BaseResponse {
|
|
||||||
isDeviceVerificationSectionEnabled: boolean;
|
|
||||||
unknownDeviceVerificationEnabled: boolean;
|
|
||||||
|
|
||||||
constructor(response: any) {
|
|
||||||
super(response);
|
|
||||||
this.isDeviceVerificationSectionEnabled = this.getResponseProperty(
|
|
||||||
"IsDeviceVerificationSectionEnabled",
|
|
||||||
);
|
|
||||||
this.unknownDeviceVerificationEnabled = this.getResponseProperty(
|
|
||||||
"UnknownDeviceVerificationEnabled",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { DisableTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/disable-two-factor-authenticator.request";
|
||||||
|
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
||||||
|
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
||||||
|
import { TwoFactorProviderRequest } from "@bitwarden/common/auth/models/request/two-factor-provider.request";
|
||||||
|
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/update-two-factor-authenticator.request";
|
||||||
|
import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/auth/models/request/update-two-factor-duo.request";
|
||||||
|
import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/update-two-factor-email.request";
|
||||||
|
import { UpdateTwoFactorWebAuthnDeleteRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn-delete.request";
|
||||||
|
import { UpdateTwoFactorWebAuthnRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn.request";
|
||||||
|
import { UpdateTwoFactorYubikeyOtpRequest } from "@bitwarden/common/auth/models/request/update-two-factor-yubikey-otp.request";
|
||||||
|
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/auth/models/response/two-factor-authenticator.response";
|
||||||
|
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||||
|
import { TwoFactorEmailResponse } from "@bitwarden/common/auth/models/response/two-factor-email.response";
|
||||||
|
import { TwoFactorProviderResponse } from "@bitwarden/common/auth/models/response/two-factor-provider.response";
|
||||||
|
import { TwoFactorRecoverResponse } from "@bitwarden/common/auth/models/response/two-factor-recover.response";
|
||||||
|
import {
|
||||||
|
TwoFactorWebAuthnResponse,
|
||||||
|
ChallengeResponse,
|
||||||
|
} from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
||||||
|
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
||||||
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
|
||||||
|
import { TwoFactorApiService } from "./two-factor-api.service";
|
||||||
|
|
||||||
|
export class DefaultTwoFactorApiService implements TwoFactorApiService {
|
||||||
|
constructor(private apiService: ApiService) {}
|
||||||
|
|
||||||
|
// Providers
|
||||||
|
|
||||||
|
async getTwoFactorProviders(): Promise<ListResponse<TwoFactorProviderResponse>> {
|
||||||
|
const response = await this.apiService.send("GET", "/two-factor", null, true, true);
|
||||||
|
return new ListResponse(response, TwoFactorProviderResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTwoFactorOrganizationProviders(
|
||||||
|
organizationId: string,
|
||||||
|
): Promise<ListResponse<TwoFactorProviderResponse>> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"GET",
|
||||||
|
`/organizations/${organizationId}/two-factor`,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new ListResponse(response, TwoFactorProviderResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticator (TOTP)
|
||||||
|
|
||||||
|
async getTwoFactorAuthenticator(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorAuthenticatorResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-authenticator",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorAuthenticatorResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorAuthenticator(
|
||||||
|
request: UpdateTwoFactorAuthenticatorRequest,
|
||||||
|
): Promise<TwoFactorAuthenticatorResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"PUT",
|
||||||
|
"/two-factor/authenticator",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorAuthenticatorResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteTwoFactorAuthenticator(
|
||||||
|
request: DisableTwoFactorAuthenticatorRequest,
|
||||||
|
): Promise<TwoFactorProviderResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"DELETE",
|
||||||
|
"/two-factor/authenticator",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorProviderResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Email
|
||||||
|
|
||||||
|
async getTwoFactorEmail(request: SecretVerificationRequest): Promise<TwoFactorEmailResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-email",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorEmailResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise<any> {
|
||||||
|
return this.apiService.send("POST", "/two-factor/send-email", request, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async postTwoFactorEmail(request: TwoFactorEmailRequest): Promise<any> {
|
||||||
|
return this.apiService.send("POST", "/two-factor/send-email-login", request, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise<TwoFactorEmailResponse> {
|
||||||
|
const response = await this.apiService.send("PUT", "/two-factor/email", request, true, true);
|
||||||
|
return new TwoFactorEmailResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duo
|
||||||
|
|
||||||
|
async getTwoFactorDuo(request: SecretVerificationRequest): Promise<TwoFactorDuoResponse> {
|
||||||
|
const response = await this.apiService.send("POST", "/two-factor/get-duo", request, true, true);
|
||||||
|
return new TwoFactorDuoResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTwoFactorOrganizationDuo(
|
||||||
|
organizationId: string,
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorDuoResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
`/organizations/${organizationId}/two-factor/get-duo`,
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorDuoResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise<TwoFactorDuoResponse> {
|
||||||
|
const response = await this.apiService.send("PUT", "/two-factor/duo", request, true, true);
|
||||||
|
return new TwoFactorDuoResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorOrganizationDuo(
|
||||||
|
organizationId: string,
|
||||||
|
request: UpdateTwoFactorDuoRequest,
|
||||||
|
): Promise<TwoFactorDuoResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"PUT",
|
||||||
|
`/organizations/${organizationId}/two-factor/duo`,
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorDuoResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// YubiKey
|
||||||
|
|
||||||
|
async getTwoFactorYubiKey(request: SecretVerificationRequest): Promise<TwoFactorYubiKeyResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-yubikey",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorYubiKeyResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorYubiKey(
|
||||||
|
request: UpdateTwoFactorYubikeyOtpRequest,
|
||||||
|
): Promise<TwoFactorYubiKeyResponse> {
|
||||||
|
const response = await this.apiService.send("PUT", "/two-factor/yubikey", request, true, true);
|
||||||
|
return new TwoFactorYubiKeyResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebAuthn
|
||||||
|
|
||||||
|
async getTwoFactorWebAuthn(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorWebAuthnResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-webauthn",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorWebAuthnResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTwoFactorWebAuthnChallenge(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<ChallengeResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-webauthn-challenge",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new ChallengeResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorWebAuthn(
|
||||||
|
request: UpdateTwoFactorWebAuthnRequest,
|
||||||
|
): Promise<TwoFactorWebAuthnResponse> {
|
||||||
|
const deviceResponse = request.deviceResponse.response as AuthenticatorAttestationResponse;
|
||||||
|
const body: any = Object.assign({}, request);
|
||||||
|
|
||||||
|
body.deviceResponse = {
|
||||||
|
id: request.deviceResponse.id,
|
||||||
|
rawId: btoa(request.deviceResponse.id),
|
||||||
|
type: request.deviceResponse.type,
|
||||||
|
extensions: request.deviceResponse.getClientExtensionResults(),
|
||||||
|
response: {
|
||||||
|
AttestationObject: Utils.fromBufferToB64(deviceResponse.attestationObject),
|
||||||
|
clientDataJson: Utils.fromBufferToB64(deviceResponse.clientDataJSON),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await this.apiService.send("PUT", "/two-factor/webauthn", body, true, true);
|
||||||
|
return new TwoFactorWebAuthnResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteTwoFactorWebAuthn(
|
||||||
|
request: UpdateTwoFactorWebAuthnDeleteRequest,
|
||||||
|
): Promise<TwoFactorWebAuthnResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"DELETE",
|
||||||
|
"/two-factor/webauthn",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorWebAuthnResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recovery Code
|
||||||
|
|
||||||
|
async getTwoFactorRecover(request: SecretVerificationRequest): Promise<TwoFactorRecoverResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-recover",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorRecoverResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable
|
||||||
|
|
||||||
|
async putTwoFactorDisable(request: TwoFactorProviderRequest): Promise<TwoFactorProviderResponse> {
|
||||||
|
const response = await this.apiService.send("PUT", "/two-factor/disable", request, true, true);
|
||||||
|
return new TwoFactorProviderResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
async putTwoFactorOrganizationDisable(
|
||||||
|
organizationId: string,
|
||||||
|
request: TwoFactorProviderRequest,
|
||||||
|
): Promise<TwoFactorProviderResponse> {
|
||||||
|
const response = await this.apiService.send(
|
||||||
|
"PUT",
|
||||||
|
`/organizations/${organizationId}/two-factor/disable`,
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
return new TwoFactorProviderResponse(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
libs/common/src/auth/two-factor/index.ts
Normal file
2
libs/common/src/auth/two-factor/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export { TwoFactorApiService } from "./two-factor-api.service";
|
||||||
|
export { DefaultTwoFactorApiService } from "./default-two-factor-api.service";
|
||||||
697
libs/common/src/auth/two-factor/two-factor-api.service.spec.ts
Normal file
697
libs/common/src/auth/two-factor/two-factor-api.service.spec.ts
Normal file
@@ -0,0 +1,697 @@
|
|||||||
|
import { mock, MockProxy } from "jest-mock-extended";
|
||||||
|
|
||||||
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
|
import { DisableTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/disable-two-factor-authenticator.request";
|
||||||
|
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
||||||
|
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
||||||
|
import { TwoFactorProviderRequest } from "@bitwarden/common/auth/models/request/two-factor-provider.request";
|
||||||
|
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/update-two-factor-authenticator.request";
|
||||||
|
import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/auth/models/request/update-two-factor-duo.request";
|
||||||
|
import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/update-two-factor-email.request";
|
||||||
|
import { UpdateTwoFactorWebAuthnDeleteRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn-delete.request";
|
||||||
|
import { UpdateTwoFactorWebAuthnRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn.request";
|
||||||
|
import { UpdateTwoFactorYubikeyOtpRequest } from "@bitwarden/common/auth/models/request/update-two-factor-yubikey-otp.request";
|
||||||
|
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/auth/models/response/two-factor-authenticator.response";
|
||||||
|
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||||
|
import { TwoFactorEmailResponse } from "@bitwarden/common/auth/models/response/two-factor-email.response";
|
||||||
|
import { TwoFactorProviderResponse } from "@bitwarden/common/auth/models/response/two-factor-provider.response";
|
||||||
|
import { TwoFactorRecoverResponse } from "@bitwarden/common/auth/models/response/two-factor-recover.response";
|
||||||
|
import {
|
||||||
|
TwoFactorWebAuthnResponse,
|
||||||
|
ChallengeResponse,
|
||||||
|
} from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
||||||
|
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
||||||
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
|
|
||||||
|
import { DefaultTwoFactorApiService } from "./default-two-factor-api.service";
|
||||||
|
|
||||||
|
describe("TwoFactorApiService", () => {
|
||||||
|
let apiService: MockProxy<ApiService>;
|
||||||
|
let twoFactorApiService: DefaultTwoFactorApiService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
apiService = mock<ApiService>();
|
||||||
|
twoFactorApiService = new DefaultTwoFactorApiService(apiService);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Two-Factor Providers", () => {
|
||||||
|
describe("getTwoFactorProviders", () => {
|
||||||
|
it("retrieves all enabled two-factor providers for the current user", async () => {
|
||||||
|
const mockResponse = {
|
||||||
|
data: [
|
||||||
|
{ Type: 0, Enabled: true },
|
||||||
|
{ Type: 1, Enabled: true },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorProviders();
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith("GET", "/two-factor", null, true, true);
|
||||||
|
expect(result).toBeInstanceOf(ListResponse);
|
||||||
|
expect(result.data).toHaveLength(2);
|
||||||
|
for (let i = 0; i < result.data.length; i++) {
|
||||||
|
expect(result.data[i]).toBeInstanceOf(TwoFactorProviderResponse);
|
||||||
|
expect(result.data[i].type).toBe(i);
|
||||||
|
expect(result.data[i].enabled).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getTwoFactorOrganizationProviders", () => {
|
||||||
|
it("retrieves all enabled two-factor providers for a specific organization", async () => {
|
||||||
|
const organizationId = "org-123";
|
||||||
|
const mockResponse = {
|
||||||
|
data: [{ Type: 6, Enabled: true }],
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorOrganizationProviders(organizationId);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"GET",
|
||||||
|
`/organizations/${organizationId}/two-factor`,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(ListResponse);
|
||||||
|
expect(result.data[0]).toBeInstanceOf(TwoFactorProviderResponse);
|
||||||
|
expect(result.data[0].enabled).toBe(true);
|
||||||
|
expect(result.data[0].type).toBe(6); // Duo
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Authenticator (TOTP) APIs", () => {
|
||||||
|
describe("getTwoFactorAuthenticator", () => {
|
||||||
|
it("retrieves authenticator configuration with secret key after user verification", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: false,
|
||||||
|
Key: "MFRGGZDFMZTWQ2LK",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorAuthenticator(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-authenticator",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorAuthenticatorResponse);
|
||||||
|
expect(result.enabled).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorAuthenticator", () => {
|
||||||
|
it("enables authenticator after validating the provided token", async () => {
|
||||||
|
const request = new UpdateTwoFactorAuthenticatorRequest();
|
||||||
|
request.token = "123456";
|
||||||
|
request.key = "MFRGGZDFMZTWQ2LK";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Key: "MFRGGZDFMZTWQ2LK",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorAuthenticator(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
"/two-factor/authenticator",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorAuthenticatorResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.key).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("deleteTwoFactorAuthenticator", () => {
|
||||||
|
it("disables authenticator two-factor authentication", async () => {
|
||||||
|
const request = new DisableTwoFactorAuthenticatorRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: false,
|
||||||
|
Type: 0,
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.deleteTwoFactorAuthenticator(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"DELETE",
|
||||||
|
"/two-factor/authenticator",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorProviderResponse);
|
||||||
|
expect(result.enabled).toBe(false);
|
||||||
|
expect(result.type).toBe(0); // Authenticator
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Email APIs", () => {
|
||||||
|
describe("getTwoFactorEmail", () => {
|
||||||
|
it("retrieves email two-factor configuration after user verification", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Email: "user@example.com",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorEmail(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-email",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorEmailResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.email).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("postTwoFactorEmailSetup", () => {
|
||||||
|
it("sends verification code to email address during two-factor setup", async () => {
|
||||||
|
const request = new TwoFactorEmailRequest();
|
||||||
|
request.email = "user@example.com";
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
|
||||||
|
await twoFactorApiService.postTwoFactorEmailSetup(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/send-email",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("postTwoFactorEmail", () => {
|
||||||
|
it("sends two-factor authentication code during login flow", async () => {
|
||||||
|
const request = new TwoFactorEmailRequest();
|
||||||
|
request.email = "user@example.com";
|
||||||
|
// Note: masterPasswordHash not required for login flow
|
||||||
|
|
||||||
|
await twoFactorApiService.postTwoFactorEmail(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/send-email-login",
|
||||||
|
request,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorEmail", () => {
|
||||||
|
it("enables email two-factor after validating the verification code", async () => {
|
||||||
|
const request = new UpdateTwoFactorEmailRequest();
|
||||||
|
request.email = "user@example.com";
|
||||||
|
request.token = "verification-code";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Email: "user@example.com",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorEmail(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
"/two-factor/email",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorEmailResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.email).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Duo APIs", () => {
|
||||||
|
describe("getTwoFactorDuo", () => {
|
||||||
|
it("retrieves Duo configuration for premium user after verification", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Host: "api-abc123.duosecurity.com",
|
||||||
|
ClientId: "DI9ABC1DEFGH2JKL",
|
||||||
|
ClientSecret: "client******",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorDuo(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-duo",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorDuoResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.host).toBeDefined();
|
||||||
|
expect(result.clientId).toBeDefined();
|
||||||
|
expect(result.clientSecret).toContain("******");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getTwoFactorOrganizationDuo", () => {
|
||||||
|
it("retrieves Duo configuration for organization with admin permissions", async () => {
|
||||||
|
const organizationId = "org-123";
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Host: "api-xyz789.duosecurity.com",
|
||||||
|
ClientId: "DI4XYZ9MNOP3QRS",
|
||||||
|
ClientSecret: "orgcli******",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorOrganizationDuo(
|
||||||
|
organizationId,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
`/organizations/${organizationId}/two-factor/get-duo`,
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorDuoResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.host).toBeDefined();
|
||||||
|
expect(result.clientId).toBeDefined();
|
||||||
|
expect(result.clientSecret).toContain("******");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorDuo", () => {
|
||||||
|
it("enables Duo two-factor for premium user with valid integration details", async () => {
|
||||||
|
const request = new UpdateTwoFactorDuoRequest();
|
||||||
|
request.host = "api-abc123.duosecurity.com";
|
||||||
|
request.clientId = "DI9ABC1DEFGH2JKL";
|
||||||
|
request.clientSecret = "client-secret-value-here";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Host: "api-abc123.duosecurity.com",
|
||||||
|
ClientId: "DI9ABC1DEFGH2JKL",
|
||||||
|
ClientSecret: "client******",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorDuo(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith("PUT", "/two-factor/duo", request, true, true);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorDuoResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.host).toBeDefined();
|
||||||
|
expect(result.clientId).toBeDefined();
|
||||||
|
expect(result.clientSecret).toContain("******");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorOrganizationDuo", () => {
|
||||||
|
it("enables organization-level Duo with policy management permissions", async () => {
|
||||||
|
const organizationId = "org-123";
|
||||||
|
const request = new UpdateTwoFactorDuoRequest();
|
||||||
|
request.host = "api-xyz789.duosecurity.com";
|
||||||
|
request.clientId = "DI4XYZ9MNOP3QRS";
|
||||||
|
request.clientSecret = "orgcli-secret-value-here";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Host: "api-xyz789.duosecurity.com",
|
||||||
|
ClientId: "DI4XYZ9MNOP3QRS",
|
||||||
|
ClientSecret: "orgcli******",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorOrganizationDuo(
|
||||||
|
organizationId,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
`/organizations/${organizationId}/two-factor/duo`,
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorDuoResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.host).toBeDefined();
|
||||||
|
expect(result.clientId).toBeDefined();
|
||||||
|
expect(result.clientSecret).toContain("******");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("YubiKey APIs", () => {
|
||||||
|
describe("getTwoFactorYubiKey", () => {
|
||||||
|
it("retrieves YubiKey configuration for premium user after verification", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Key1: "cccccccccccc",
|
||||||
|
Key2: "dddddddddddd",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorYubiKey(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-yubikey",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorYubiKeyResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.key1).toBeDefined();
|
||||||
|
expect(result.key2).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorYubiKey", () => {
|
||||||
|
it("enables YubiKey two-factor for premium user after validating device OTPs", async () => {
|
||||||
|
const request = new UpdateTwoFactorYubikeyOtpRequest();
|
||||||
|
request.key1 = "ccccccccccccjkhbhbhrkcitringjkrjirfjuunlnlvcghnkrtgfj";
|
||||||
|
request.key2 = "ddddddddddddvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Key1: "cccccccccccc",
|
||||||
|
Key2: "dddddddddddd",
|
||||||
|
Nfc: false,
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorYubiKey(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
"/two-factor/yubikey",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorYubiKeyResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.key1).toBeDefined();
|
||||||
|
expect(result.key2).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("WebAuthn APIs", () => {
|
||||||
|
describe("getTwoFactorWebAuthn", () => {
|
||||||
|
it("retrieves list of registered WebAuthn credentials after verification", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Keys: [
|
||||||
|
{ Name: "YubiKey 5", Id: 1, Migrated: false },
|
||||||
|
{ Name: "Security Key", Id: 2, Migrated: true },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorWebAuthn(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-webauthn",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorWebAuthnResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.keys).toHaveLength(2);
|
||||||
|
result.keys.forEach((key) => {
|
||||||
|
expect(key).toHaveProperty("name");
|
||||||
|
expect(key).toHaveProperty("id");
|
||||||
|
expect(key).toHaveProperty("migrated");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getTwoFactorWebAuthnChallenge", () => {
|
||||||
|
it("obtains cryptographic challenge for WebAuthn credential registration", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
challenge: "Y2hhbGxlbmdlLXN0cmluZw",
|
||||||
|
rp: { name: "Bitwarden" },
|
||||||
|
user: {
|
||||||
|
id: "dXNlci1pZA",
|
||||||
|
name: "user@example.com",
|
||||||
|
displayName: "User",
|
||||||
|
},
|
||||||
|
pubKeyCredParams: [{ type: "public-key", alg: -7 }], // ES256
|
||||||
|
excludeCredentials: [] as PublicKeyCredentialDescriptor[],
|
||||||
|
timeout: 60000,
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorWebAuthnChallenge(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-webauthn-challenge",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(ChallengeResponse);
|
||||||
|
expect(result.challenge).toBeDefined();
|
||||||
|
expect(result.rp).toHaveProperty("name", "Bitwarden");
|
||||||
|
expect(result.user).toHaveProperty("id");
|
||||||
|
expect(result.user).toHaveProperty("name");
|
||||||
|
expect(result.user).toHaveProperty("displayName", "User");
|
||||||
|
expect(result.pubKeyCredParams).toHaveLength(1);
|
||||||
|
expect(Number(result.timeout)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorWebAuthn", () => {
|
||||||
|
it("registers new WebAuthn credential by serializing browser credential to JSON", async () => {
|
||||||
|
const mockAttestationResponse: Partial<AuthenticatorAttestationResponse> = {
|
||||||
|
clientDataJSON: new Uint8Array([1, 2, 3]).buffer,
|
||||||
|
attestationObject: new Uint8Array([4, 5, 6]).buffer,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCredential: Partial<PublicKeyCredential> = {
|
||||||
|
id: "credential-id",
|
||||||
|
type: "public-key",
|
||||||
|
response: mockAttestationResponse as AuthenticatorAttestationResponse,
|
||||||
|
getClientExtensionResults: jest.fn().mockReturnValue({}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const request = new UpdateTwoFactorWebAuthnRequest();
|
||||||
|
request.deviceResponse = mockCredential as PublicKeyCredential;
|
||||||
|
request.name = "My Security Key";
|
||||||
|
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Keys: [{ Name: "My Security Key", Id: 1, Migrated: false }],
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorWebAuthn(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
"/two-factor/webauthn",
|
||||||
|
expect.objectContaining({
|
||||||
|
name: "My Security Key",
|
||||||
|
deviceResponse: expect.objectContaining({
|
||||||
|
id: "credential-id",
|
||||||
|
rawId: expect.any(String), // base64 encoded
|
||||||
|
type: "public-key",
|
||||||
|
extensions: {},
|
||||||
|
response: expect.objectContaining({
|
||||||
|
AttestationObject: expect.any(String), // base64 encoded
|
||||||
|
clientDataJson: expect.any(String), // base64 encoded
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorWebAuthnResponse);
|
||||||
|
expect(result.enabled).toBe(true);
|
||||||
|
expect(result.keys).toHaveLength(1);
|
||||||
|
expect(result.keys[0].name).toBeDefined();
|
||||||
|
expect(result.keys[0].id).toBeDefined();
|
||||||
|
expect(result.keys[0].migrated).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves original request object without mutation during serialization", async () => {
|
||||||
|
const mockAttestationResponse: Partial<AuthenticatorAttestationResponse> = {
|
||||||
|
clientDataJSON: new Uint8Array([1, 2, 3]).buffer,
|
||||||
|
attestationObject: new Uint8Array([4, 5, 6]).buffer,
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCredential: Partial<PublicKeyCredential> = {
|
||||||
|
id: "credential-id",
|
||||||
|
type: "public-key",
|
||||||
|
response: mockAttestationResponse as AuthenticatorAttestationResponse,
|
||||||
|
getClientExtensionResults: jest.fn().mockReturnValue({}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const request = new UpdateTwoFactorWebAuthnRequest();
|
||||||
|
request.deviceResponse = mockCredential as PublicKeyCredential;
|
||||||
|
request.name = "My Security Key";
|
||||||
|
|
||||||
|
const originalDeviceResponse = request.deviceResponse;
|
||||||
|
apiService.send.mockResolvedValue({ enabled: true, keys: [] });
|
||||||
|
|
||||||
|
await twoFactorApiService.putTwoFactorWebAuthn(request);
|
||||||
|
|
||||||
|
// Do not mutate the original request object
|
||||||
|
expect(request.deviceResponse).toBe(originalDeviceResponse);
|
||||||
|
expect(request.deviceResponse.response).toBe(mockAttestationResponse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("deleteTwoFactorWebAuthn", () => {
|
||||||
|
it("removes specific WebAuthn credential while preserving other registered keys", async () => {
|
||||||
|
const request = new UpdateTwoFactorWebAuthnDeleteRequest();
|
||||||
|
request.id = 1;
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: true,
|
||||||
|
Keys: [{ Name: "Security Key", Id: 2, Migrated: true }], // Key with id:1 removed
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.deleteTwoFactorWebAuthn(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"DELETE",
|
||||||
|
"/two-factor/webauthn",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorWebAuthnResponse);
|
||||||
|
expect(result.keys).toHaveLength(1);
|
||||||
|
expect(result.keys[0].id).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Recovery Code APIs", () => {
|
||||||
|
describe("getTwoFactorRecover", () => {
|
||||||
|
it("retrieves recovery code for regaining access when two-factor is unavailable", async () => {
|
||||||
|
const request = new SecretVerificationRequest();
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Code: "ABCD-EFGH-IJKL-MNOP-QRST-UVWX-YZ12",
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.getTwoFactorRecover(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"POST",
|
||||||
|
"/two-factor/get-recover",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorRecoverResponse);
|
||||||
|
expect(result.code).toBeDefined();
|
||||||
|
expect(result.code).toMatch(/^[A-Z0-9-]+$/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Disable APIs", () => {
|
||||||
|
describe("putTwoFactorDisable", () => {
|
||||||
|
it("disables specified two-factor provider for current user", async () => {
|
||||||
|
const request = new TwoFactorProviderRequest();
|
||||||
|
request.type = 0; // Authenticator
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: false,
|
||||||
|
Type: 0,
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorDisable(request);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
"/two-factor/disable",
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorProviderResponse);
|
||||||
|
expect(result.enabled).toBe(false);
|
||||||
|
expect(result.type).toBe(0); // Authenticator
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("putTwoFactorOrganizationDisable", () => {
|
||||||
|
it("disables two-factor provider for organization with policy management permissions", async () => {
|
||||||
|
const organizationId = "org-123";
|
||||||
|
const request = new TwoFactorProviderRequest();
|
||||||
|
request.type = 6; // Duo
|
||||||
|
request.masterPasswordHash = "master-password-hash";
|
||||||
|
const mockResponse = {
|
||||||
|
Enabled: false,
|
||||||
|
Type: 6,
|
||||||
|
};
|
||||||
|
apiService.send.mockResolvedValue(mockResponse);
|
||||||
|
|
||||||
|
const result = await twoFactorApiService.putTwoFactorOrganizationDisable(
|
||||||
|
organizationId,
|
||||||
|
request,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(apiService.send).toHaveBeenCalledWith(
|
||||||
|
"PUT",
|
||||||
|
`/organizations/${organizationId}/two-factor/disable`,
|
||||||
|
request,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(TwoFactorProviderResponse);
|
||||||
|
expect(result.enabled).toBe(false);
|
||||||
|
expect(result.type).toBe(6); // Duo
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
292
libs/common/src/auth/two-factor/two-factor-api.service.ts
Normal file
292
libs/common/src/auth/two-factor/two-factor-api.service.ts
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
import { DisableTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/disable-two-factor-authenticator.request";
|
||||||
|
import { SecretVerificationRequest } from "@bitwarden/common/auth/models/request/secret-verification.request";
|
||||||
|
import { TwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/two-factor-email.request";
|
||||||
|
import { TwoFactorProviderRequest } from "@bitwarden/common/auth/models/request/two-factor-provider.request";
|
||||||
|
import { UpdateTwoFactorAuthenticatorRequest } from "@bitwarden/common/auth/models/request/update-two-factor-authenticator.request";
|
||||||
|
import { UpdateTwoFactorDuoRequest } from "@bitwarden/common/auth/models/request/update-two-factor-duo.request";
|
||||||
|
import { UpdateTwoFactorEmailRequest } from "@bitwarden/common/auth/models/request/update-two-factor-email.request";
|
||||||
|
import { UpdateTwoFactorWebAuthnDeleteRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn-delete.request";
|
||||||
|
import { UpdateTwoFactorWebAuthnRequest } from "@bitwarden/common/auth/models/request/update-two-factor-web-authn.request";
|
||||||
|
import { UpdateTwoFactorYubikeyOtpRequest } from "@bitwarden/common/auth/models/request/update-two-factor-yubikey-otp.request";
|
||||||
|
import { TwoFactorAuthenticatorResponse } from "@bitwarden/common/auth/models/response/two-factor-authenticator.response";
|
||||||
|
import { TwoFactorDuoResponse } from "@bitwarden/common/auth/models/response/two-factor-duo.response";
|
||||||
|
import { TwoFactorEmailResponse } from "@bitwarden/common/auth/models/response/two-factor-email.response";
|
||||||
|
import { TwoFactorProviderResponse } from "@bitwarden/common/auth/models/response/two-factor-provider.response";
|
||||||
|
import { TwoFactorRecoverResponse } from "@bitwarden/common/auth/models/response/two-factor-recover.response";
|
||||||
|
import {
|
||||||
|
ChallengeResponse,
|
||||||
|
TwoFactorWebAuthnResponse,
|
||||||
|
} from "@bitwarden/common/auth/models/response/two-factor-web-authn.response";
|
||||||
|
import { TwoFactorYubiKeyResponse } from "@bitwarden/common/auth/models/response/two-factor-yubi-key.response";
|
||||||
|
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service abstraction for two-factor authentication API operations.
|
||||||
|
* Provides methods for managing various two-factor authentication providers including
|
||||||
|
* authenticator apps (TOTP), email, Duo, YubiKey, WebAuthn (FIDO2), and recovery codes.
|
||||||
|
*
|
||||||
|
* All methods that retrieve sensitive configuration data require user verification via
|
||||||
|
* SecretVerificationRequest. Premium-tier providers (Duo, YubiKey) require an active
|
||||||
|
* premium subscription. Organization-level methods require appropriate administrative permissions.
|
||||||
|
*/
|
||||||
|
export abstract class TwoFactorApiService {
|
||||||
|
/**
|
||||||
|
* Gets a list of all enabled two-factor providers for the current user.
|
||||||
|
*
|
||||||
|
* @returns A promise that resolves to a list response containing enabled two-factor provider configurations.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorProviders(): Promise<ListResponse<TwoFactorProviderResponse>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all enabled two-factor providers for an organization.
|
||||||
|
* Requires organization administrator permissions.
|
||||||
|
*
|
||||||
|
* @param organizationId The ID of the organization.
|
||||||
|
* @returns A promise that resolves to a list response containing enabled two-factor provider configurations.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorOrganizationProviders(
|
||||||
|
organizationId: string,
|
||||||
|
): Promise<ListResponse<TwoFactorProviderResponse>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the authenticator (TOTP) two-factor configuration for the current user.
|
||||||
|
* Returns the shared secret key and user verification token needed for setup.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the authenticator configuration including the secret key.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorAuthenticator(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorAuthenticatorResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the email two-factor configuration for the current user.
|
||||||
|
* Returns the configured email address and enabled status.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the email two-factor configuration.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorEmail(request: SecretVerificationRequest): Promise<TwoFactorEmailResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Duo two-factor configuration for the current user.
|
||||||
|
* Returns Duo integration configuration details.
|
||||||
|
* Requires user verification and an active premium subscription.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the Duo configuration.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorDuo(request: SecretVerificationRequest): Promise<TwoFactorDuoResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Duo two-factor configuration for an organization.
|
||||||
|
* Returns organization-level Duo integration configuration.
|
||||||
|
* Requires user verification and organization policy management permissions.
|
||||||
|
*
|
||||||
|
* @param organizationId The ID of the organization.
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the organization Duo configuration.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorOrganizationDuo(
|
||||||
|
organizationId: string,
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorDuoResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the YubiKey OTP two-factor configuration for the current user.
|
||||||
|
* Returns configured YubiKey device identifiers (multiple keys supported).
|
||||||
|
* Requires user verification and an active premium subscription.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the YubiKey configuration.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorYubiKey(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorYubiKeyResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the WebAuthn (FIDO2) two-factor configuration for the current user.
|
||||||
|
* Returns a list of registered WebAuthn credentials with their names and IDs.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the WebAuthn configuration including registered credentials.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorWebAuthn(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorWebAuthnResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a WebAuthn challenge for registering a new WebAuthn credential.
|
||||||
|
* This must be called before putTwoFactorWebAuthn to obtain the cryptographic challenge
|
||||||
|
* required for credential creation. The challenge is used by the browser's WebAuthn API.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the credential creation options containing the challenge.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorWebAuthnChallenge(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<ChallengeResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the recovery code configuration for the current user.
|
||||||
|
* Returns the recovery code that can be used to regain access if other two-factor methods are unavailable.
|
||||||
|
* The recovery code should be stored securely by the user.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The secret verification request to authorize the operation.
|
||||||
|
* @returns A promise that resolves to the recovery code configuration.
|
||||||
|
*/
|
||||||
|
abstract getTwoFactorRecover(
|
||||||
|
request: SecretVerificationRequest,
|
||||||
|
): Promise<TwoFactorRecoverResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or updates the authenticator (TOTP) two-factor provider.
|
||||||
|
* Validates the provided token against the shared secret before enabling.
|
||||||
|
* The token must be generated by an authenticator app using the secret key.
|
||||||
|
*
|
||||||
|
* @param request The request containing the authenticator configuration and verification token.
|
||||||
|
* @returns A promise that resolves to the updated authenticator configuration.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorAuthenticator(
|
||||||
|
request: UpdateTwoFactorAuthenticatorRequest,
|
||||||
|
): Promise<TwoFactorAuthenticatorResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the authenticator (TOTP) two-factor provider for the current user.
|
||||||
|
* Requires user verification token to confirm the operation.
|
||||||
|
*
|
||||||
|
* @param request The request containing verification credentials to disable the provider.
|
||||||
|
* @returns A promise that resolves to the updated provider status.
|
||||||
|
*/
|
||||||
|
abstract deleteTwoFactorAuthenticator(
|
||||||
|
request: DisableTwoFactorAuthenticatorRequest,
|
||||||
|
): Promise<TwoFactorProviderResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or updates the email two-factor provider.
|
||||||
|
* Validates the email verification token sent via postTwoFactorEmailSetup before enabling.
|
||||||
|
* The token must match the code sent to the specified email address.
|
||||||
|
*
|
||||||
|
* @param request The request containing the email configuration and verification token.
|
||||||
|
* @returns A promise that resolves to the updated email two-factor configuration.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise<TwoFactorEmailResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or updates the Duo two-factor provider for the current user.
|
||||||
|
* Validates the Duo configuration (client ID, client secret, and host) before enabling.
|
||||||
|
* Requires user verification and an active premium subscription.
|
||||||
|
*
|
||||||
|
* @param request The request containing the Duo integration configuration.
|
||||||
|
* @returns A promise that resolves to the updated Duo configuration.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise<TwoFactorDuoResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or updates the Duo two-factor provider for an organization.
|
||||||
|
* Validates the Duo configuration (client ID, client secret, and host) before enabling.
|
||||||
|
* Requires user verification and organization policy management permissions.
|
||||||
|
*
|
||||||
|
* @param organizationId The ID of the organization.
|
||||||
|
* @param request The request containing the Duo integration configuration.
|
||||||
|
* @returns A promise that resolves to the updated organization Duo configuration.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorOrganizationDuo(
|
||||||
|
organizationId: string,
|
||||||
|
request: UpdateTwoFactorDuoRequest,
|
||||||
|
): Promise<TwoFactorDuoResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or updates the YubiKey OTP two-factor provider.
|
||||||
|
* Validates each provided YubiKey by testing an OTP from the device.
|
||||||
|
* Supports up to 5 YubiKey devices. Empty key slots are allowed.
|
||||||
|
* Requires user verification and an active premium subscription.
|
||||||
|
* Includes a 2-second delay on validation failure to prevent timing attacks.
|
||||||
|
*
|
||||||
|
* @param request The request containing YubiKey device identifiers and test OTPs.
|
||||||
|
* @returns A promise that resolves to the updated YubiKey configuration.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorYubiKey(
|
||||||
|
request: UpdateTwoFactorYubikeyOtpRequest,
|
||||||
|
): Promise<TwoFactorYubiKeyResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a new WebAuthn (FIDO2) credential for two-factor authentication.
|
||||||
|
* Must be called after getTwoFactorWebAuthnChallenge to complete the registration flow.
|
||||||
|
* The device response contains the signed challenge from the authenticator device.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The request containing the WebAuthn credential creation response from the browser.
|
||||||
|
* @returns A promise that resolves to the updated WebAuthn configuration with the new credential.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorWebAuthn(
|
||||||
|
request: UpdateTwoFactorWebAuthnRequest,
|
||||||
|
): Promise<TwoFactorWebAuthnResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a specific WebAuthn (FIDO2) credential from the user's account.
|
||||||
|
* The credential will no longer be usable for two-factor authentication.
|
||||||
|
* Other registered WebAuthn credentials remain active.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The request containing the credential ID to remove.
|
||||||
|
* @returns A promise that resolves to the updated WebAuthn configuration.
|
||||||
|
*/
|
||||||
|
abstract deleteTwoFactorWebAuthn(
|
||||||
|
request: UpdateTwoFactorWebAuthnDeleteRequest,
|
||||||
|
): Promise<TwoFactorWebAuthnResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables a specific two-factor provider for the current user.
|
||||||
|
* The provider will no longer be required or usable for authentication.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The request specifying which provider type to disable.
|
||||||
|
* @returns A promise that resolves to the updated provider status.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorDisable(
|
||||||
|
request: TwoFactorProviderRequest,
|
||||||
|
): Promise<TwoFactorProviderResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables a specific two-factor provider for an organization.
|
||||||
|
* The provider will no longer be available for organization members.
|
||||||
|
* Requires user verification and organization policy management permissions.
|
||||||
|
*
|
||||||
|
* @param organizationId The ID of the organization.
|
||||||
|
* @param request The request specifying which provider type to disable.
|
||||||
|
* @returns A promise that resolves to the updated provider status.
|
||||||
|
*/
|
||||||
|
abstract putTwoFactorOrganizationDisable(
|
||||||
|
organizationId: string,
|
||||||
|
request: TwoFactorProviderRequest,
|
||||||
|
): Promise<TwoFactorProviderResponse>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates email two-factor setup by sending a verification code to the specified email address.
|
||||||
|
* This is the first step in enabling email two-factor authentication.
|
||||||
|
* The verification code must be provided to putTwoFactorEmail to complete setup.
|
||||||
|
* Only used during initial configuration, not during login flows.
|
||||||
|
* Requires user verification via master password or OTP.
|
||||||
|
*
|
||||||
|
* @param request The request containing the email address for two-factor setup.
|
||||||
|
* @returns A promise that resolves when the verification email has been sent.
|
||||||
|
*/
|
||||||
|
abstract postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise<any>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a two-factor authentication code via email during the login flow.
|
||||||
|
* Supports multiple authentication contexts including standard login, SSO, and passwordless flows.
|
||||||
|
* This is used to deliver codes during authentication, not during initial setup.
|
||||||
|
* May be called without authentication for login scenarios.
|
||||||
|
*
|
||||||
|
* @param request The request to send the two-factor code, optionally including SSO or auth request tokens.
|
||||||
|
* @returns A promise that resolves when the authentication email has been sent.
|
||||||
|
*/
|
||||||
|
abstract postTwoFactorEmail(request: TwoFactorEmailRequest): Promise<any>;
|
||||||
|
}
|
||||||
@@ -48,8 +48,6 @@ import {
|
|||||||
import { SelectionReadOnlyResponse } from "../admin-console/models/response/selection-read-only.response";
|
import { SelectionReadOnlyResponse } from "../admin-console/models/response/selection-read-only.response";
|
||||||
import { AccountService } from "../auth/abstractions/account.service";
|
import { AccountService } from "../auth/abstractions/account.service";
|
||||||
import { TokenService } from "../auth/abstractions/token.service";
|
import { TokenService } from "../auth/abstractions/token.service";
|
||||||
import { DeviceVerificationRequest } from "../auth/models/request/device-verification.request";
|
|
||||||
import { DisableTwoFactorAuthenticatorRequest } from "../auth/models/request/disable-two-factor-authenticator.request";
|
|
||||||
import { EmailTokenRequest } from "../auth/models/request/email-token.request";
|
import { EmailTokenRequest } from "../auth/models/request/email-token.request";
|
||||||
import { EmailRequest } from "../auth/models/request/email.request";
|
import { EmailRequest } from "../auth/models/request/email.request";
|
||||||
import { DeviceRequest } from "../auth/models/request/identity-token/device.request";
|
import { DeviceRequest } from "../auth/models/request/identity-token/device.request";
|
||||||
@@ -61,34 +59,15 @@ import { WebAuthnLoginTokenRequest } from "../auth/models/request/identity-token
|
|||||||
import { PasswordHintRequest } from "../auth/models/request/password-hint.request";
|
import { PasswordHintRequest } from "../auth/models/request/password-hint.request";
|
||||||
import { PasswordlessAuthRequest } from "../auth/models/request/passwordless-auth.request";
|
import { PasswordlessAuthRequest } from "../auth/models/request/passwordless-auth.request";
|
||||||
import { SecretVerificationRequest } from "../auth/models/request/secret-verification.request";
|
import { SecretVerificationRequest } from "../auth/models/request/secret-verification.request";
|
||||||
import { TwoFactorEmailRequest } from "../auth/models/request/two-factor-email.request";
|
|
||||||
import { TwoFactorProviderRequest } from "../auth/models/request/two-factor-provider.request";
|
|
||||||
import { UpdateProfileRequest } from "../auth/models/request/update-profile.request";
|
import { UpdateProfileRequest } from "../auth/models/request/update-profile.request";
|
||||||
import { UpdateTwoFactorAuthenticatorRequest } from "../auth/models/request/update-two-factor-authenticator.request";
|
|
||||||
import { UpdateTwoFactorDuoRequest } from "../auth/models/request/update-two-factor-duo.request";
|
|
||||||
import { UpdateTwoFactorEmailRequest } from "../auth/models/request/update-two-factor-email.request";
|
|
||||||
import { UpdateTwoFactorWebAuthnDeleteRequest } from "../auth/models/request/update-two-factor-web-authn-delete.request";
|
|
||||||
import { UpdateTwoFactorWebAuthnRequest } from "../auth/models/request/update-two-factor-web-authn.request";
|
|
||||||
import { UpdateTwoFactorYubikeyOtpRequest } from "../auth/models/request/update-two-factor-yubikey-otp.request";
|
|
||||||
import { ApiKeyResponse } from "../auth/models/response/api-key.response";
|
import { ApiKeyResponse } from "../auth/models/response/api-key.response";
|
||||||
import { AuthRequestResponse } from "../auth/models/response/auth-request.response";
|
import { AuthRequestResponse } from "../auth/models/response/auth-request.response";
|
||||||
import { DeviceVerificationResponse } from "../auth/models/response/device-verification.response";
|
|
||||||
import { IdentityDeviceVerificationResponse } from "../auth/models/response/identity-device-verification.response";
|
import { IdentityDeviceVerificationResponse } from "../auth/models/response/identity-device-verification.response";
|
||||||
import { IdentityTokenResponse } from "../auth/models/response/identity-token.response";
|
import { IdentityTokenResponse } from "../auth/models/response/identity-token.response";
|
||||||
import { IdentityTwoFactorResponse } from "../auth/models/response/identity-two-factor.response";
|
import { IdentityTwoFactorResponse } from "../auth/models/response/identity-two-factor.response";
|
||||||
import { KeyConnectorUserKeyResponse } from "../auth/models/response/key-connector-user-key.response";
|
import { KeyConnectorUserKeyResponse } from "../auth/models/response/key-connector-user-key.response";
|
||||||
import { PreloginResponse } from "../auth/models/response/prelogin.response";
|
import { PreloginResponse } from "../auth/models/response/prelogin.response";
|
||||||
import { SsoPreValidateResponse } from "../auth/models/response/sso-pre-validate.response";
|
import { SsoPreValidateResponse } from "../auth/models/response/sso-pre-validate.response";
|
||||||
import { TwoFactorAuthenticatorResponse } from "../auth/models/response/two-factor-authenticator.response";
|
|
||||||
import { TwoFactorDuoResponse } from "../auth/models/response/two-factor-duo.response";
|
|
||||||
import { TwoFactorEmailResponse } from "../auth/models/response/two-factor-email.response";
|
|
||||||
import { TwoFactorProviderResponse } from "../auth/models/response/two-factor-provider.response";
|
|
||||||
import { TwoFactorRecoverResponse } from "../auth/models/response/two-factor-recover.response";
|
|
||||||
import {
|
|
||||||
ChallengeResponse,
|
|
||||||
TwoFactorWebAuthnResponse,
|
|
||||||
} from "../auth/models/response/two-factor-web-authn.response";
|
|
||||||
import { TwoFactorYubiKeyResponse } from "../auth/models/response/two-factor-yubi-key.response";
|
|
||||||
import { BitPayInvoiceRequest } from "../billing/models/request/bit-pay-invoice.request";
|
import { BitPayInvoiceRequest } from "../billing/models/request/bit-pay-invoice.request";
|
||||||
import { BillingHistoryResponse } from "../billing/models/response/billing-history.response";
|
import { BillingHistoryResponse } from "../billing/models/response/billing-history.response";
|
||||||
import { PaymentResponse } from "../billing/models/response/payment.response";
|
import { PaymentResponse } from "../billing/models/response/payment.response";
|
||||||
@@ -809,205 +788,6 @@ export class ApiService implements ApiServiceAbstraction {
|
|||||||
return new SyncResponse(r);
|
return new SyncResponse(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Two-factor APIs
|
|
||||||
|
|
||||||
async getTwoFactorProviders(): Promise<ListResponse<TwoFactorProviderResponse>> {
|
|
||||||
const r = await this.send("GET", "/two-factor", null, true, true);
|
|
||||||
return new ListResponse(r, TwoFactorProviderResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorOrganizationProviders(
|
|
||||||
organizationId: string,
|
|
||||||
): Promise<ListResponse<TwoFactorProviderResponse>> {
|
|
||||||
const r = await this.send(
|
|
||||||
"GET",
|
|
||||||
"/organizations/" + organizationId + "/two-factor",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return new ListResponse(r, TwoFactorProviderResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorAuthenticator(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorAuthenticatorResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-authenticator", request, true, true);
|
|
||||||
return new TwoFactorAuthenticatorResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorEmail(request: SecretVerificationRequest): Promise<TwoFactorEmailResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-email", request, true, true);
|
|
||||||
return new TwoFactorEmailResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorDuo(request: SecretVerificationRequest): Promise<TwoFactorDuoResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-duo", request, true, true);
|
|
||||||
return new TwoFactorDuoResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorOrganizationDuo(
|
|
||||||
organizationId: string,
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorDuoResponse> {
|
|
||||||
const r = await this.send(
|
|
||||||
"POST",
|
|
||||||
"/organizations/" + organizationId + "/two-factor/get-duo",
|
|
||||||
request,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return new TwoFactorDuoResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorYubiKey(request: SecretVerificationRequest): Promise<TwoFactorYubiKeyResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-yubikey", request, true, true);
|
|
||||||
return new TwoFactorYubiKeyResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorWebAuthn(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<TwoFactorWebAuthnResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-webauthn", request, true, true);
|
|
||||||
return new TwoFactorWebAuthnResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorWebAuthnChallenge(
|
|
||||||
request: SecretVerificationRequest,
|
|
||||||
): Promise<ChallengeResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-webauthn-challenge", request, true, true);
|
|
||||||
return new ChallengeResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTwoFactorRecover(request: SecretVerificationRequest): Promise<TwoFactorRecoverResponse> {
|
|
||||||
const r = await this.send("POST", "/two-factor/get-recover", request, true, true);
|
|
||||||
return new TwoFactorRecoverResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorAuthenticator(
|
|
||||||
request: UpdateTwoFactorAuthenticatorRequest,
|
|
||||||
): Promise<TwoFactorAuthenticatorResponse> {
|
|
||||||
const r = await this.send("PUT", "/two-factor/authenticator", request, true, true);
|
|
||||||
return new TwoFactorAuthenticatorResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteTwoFactorAuthenticator(
|
|
||||||
request: DisableTwoFactorAuthenticatorRequest,
|
|
||||||
): Promise<TwoFactorProviderResponse> {
|
|
||||||
const r = await this.send("DELETE", "/two-factor/authenticator", request, true, true);
|
|
||||||
return new TwoFactorProviderResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise<TwoFactorEmailResponse> {
|
|
||||||
const r = await this.send("PUT", "/two-factor/email", request, true, true);
|
|
||||||
return new TwoFactorEmailResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise<TwoFactorDuoResponse> {
|
|
||||||
const r = await this.send("PUT", "/two-factor/duo", request, true, true);
|
|
||||||
return new TwoFactorDuoResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorOrganizationDuo(
|
|
||||||
organizationId: string,
|
|
||||||
request: UpdateTwoFactorDuoRequest,
|
|
||||||
): Promise<TwoFactorDuoResponse> {
|
|
||||||
const r = await this.send(
|
|
||||||
"PUT",
|
|
||||||
"/organizations/" + organizationId + "/two-factor/duo",
|
|
||||||
request,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return new TwoFactorDuoResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorYubiKey(
|
|
||||||
request: UpdateTwoFactorYubikeyOtpRequest,
|
|
||||||
): Promise<TwoFactorYubiKeyResponse> {
|
|
||||||
const r = await this.send("PUT", "/two-factor/yubikey", request, true, true);
|
|
||||||
return new TwoFactorYubiKeyResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorWebAuthn(
|
|
||||||
request: UpdateTwoFactorWebAuthnRequest,
|
|
||||||
): Promise<TwoFactorWebAuthnResponse> {
|
|
||||||
const response = request.deviceResponse.response as AuthenticatorAttestationResponse;
|
|
||||||
const data: any = Object.assign({}, request);
|
|
||||||
|
|
||||||
data.deviceResponse = {
|
|
||||||
id: request.deviceResponse.id,
|
|
||||||
rawId: btoa(request.deviceResponse.id),
|
|
||||||
type: request.deviceResponse.type,
|
|
||||||
extensions: request.deviceResponse.getClientExtensionResults(),
|
|
||||||
response: {
|
|
||||||
AttestationObject: Utils.fromBufferToB64(response.attestationObject),
|
|
||||||
clientDataJson: Utils.fromBufferToB64(response.clientDataJSON),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const r = await this.send("PUT", "/two-factor/webauthn", data, true, true);
|
|
||||||
return new TwoFactorWebAuthnResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteTwoFactorWebAuthn(
|
|
||||||
request: UpdateTwoFactorWebAuthnDeleteRequest,
|
|
||||||
): Promise<TwoFactorWebAuthnResponse> {
|
|
||||||
const r = await this.send("DELETE", "/two-factor/webauthn", request, true, true);
|
|
||||||
return new TwoFactorWebAuthnResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorDisable(request: TwoFactorProviderRequest): Promise<TwoFactorProviderResponse> {
|
|
||||||
const r = await this.send("PUT", "/two-factor/disable", request, true, true);
|
|
||||||
return new TwoFactorProviderResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putTwoFactorOrganizationDisable(
|
|
||||||
organizationId: string,
|
|
||||||
request: TwoFactorProviderRequest,
|
|
||||||
): Promise<TwoFactorProviderResponse> {
|
|
||||||
const r = await this.send(
|
|
||||||
"PUT",
|
|
||||||
"/organizations/" + organizationId + "/two-factor/disable",
|
|
||||||
request,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return new TwoFactorProviderResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise<any> {
|
|
||||||
return this.send("POST", "/two-factor/send-email", request, true, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
postTwoFactorEmail(request: TwoFactorEmailRequest): Promise<any> {
|
|
||||||
return this.send("POST", "/two-factor/send-email-login", request, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getDeviceVerificationSettings(): Promise<DeviceVerificationResponse> {
|
|
||||||
const r = await this.send(
|
|
||||||
"GET",
|
|
||||||
"/two-factor/get-device-verification-settings",
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return new DeviceVerificationResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
async putDeviceVerificationSettings(
|
|
||||||
request: DeviceVerificationRequest,
|
|
||||||
): Promise<DeviceVerificationResponse> {
|
|
||||||
const r = await this.send(
|
|
||||||
"PUT",
|
|
||||||
"/two-factor/device-verification-settings",
|
|
||||||
request,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
return new DeviceVerificationResponse(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Organization APIs
|
// Organization APIs
|
||||||
|
|
||||||
async getCloudCommunicationsEnabled(): Promise<boolean> {
|
async getCloudCommunicationsEnabled(): Promise<boolean> {
|
||||||
|
|||||||
Reference in New Issue
Block a user