added feature flag, and services for tokenable when adding Authenticator two factor; (#10261)
This commit is contained in:
parent
b9eb4003a1
commit
b3f7bad4b2
|
@ -7,9 +7,12 @@ 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 { 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 { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||||
|
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||||
|
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";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
|
@ -43,6 +46,7 @@ export class TwoFactorAuthenticatorComponent
|
||||||
@Output() onChangeStatus = new EventEmitter<boolean>();
|
@Output() onChangeStatus = new EventEmitter<boolean>();
|
||||||
type = TwoFactorProviderType.Authenticator;
|
type = TwoFactorProviderType.Authenticator;
|
||||||
key: string;
|
key: string;
|
||||||
|
private userVerificationToken: string;
|
||||||
|
|
||||||
override componentName = "app-two-factor-authenticator";
|
override componentName = "app-two-factor-authenticator";
|
||||||
qrScriptError = false;
|
qrScriptError = false;
|
||||||
|
@ -63,6 +67,7 @@ export class TwoFactorAuthenticatorComponent
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
private accountService: AccountService,
|
private accountService: AccountService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
|
private configService: ConfigService,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
apiService,
|
apiService,
|
||||||
|
@ -112,16 +117,46 @@ export class TwoFactorAuthenticatorComponent
|
||||||
const request = await this.buildRequestModel(UpdateTwoFactorAuthenticatorRequest);
|
const request = await this.buildRequestModel(UpdateTwoFactorAuthenticatorRequest);
|
||||||
request.token = this.formGroup.value.token;
|
request.token = this.formGroup.value.token;
|
||||||
request.key = this.key;
|
request.key = this.key;
|
||||||
|
request.userVerificationToken = this.userVerificationToken;
|
||||||
|
|
||||||
const response = await this.apiService.putTwoFactorAuthenticator(request);
|
const response = await this.apiService.putTwoFactorAuthenticator(request);
|
||||||
await this.processResponse(response);
|
await this.processResponse(response);
|
||||||
this.onUpdated.emit(true);
|
this.onUpdated.emit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override async disableMethod() {
|
||||||
|
const twoFactorAuthenticatorTokenFeatureFlag = await this.configService.getFeatureFlag(
|
||||||
|
FeatureFlag.AuthenticatorTwoFactorToken,
|
||||||
|
);
|
||||||
|
if (twoFactorAuthenticatorTokenFeatureFlag === false) {
|
||||||
|
return super.disableMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmed = await this.dialogService.openSimpleDialog({
|
||||||
|
title: { key: "disable" },
|
||||||
|
content: { key: "twoStepDisableDesc" },
|
||||||
|
type: "warning",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = await this.buildRequestModel(DisableTwoFactorAuthenticatorRequest);
|
||||||
|
request.type = this.type;
|
||||||
|
request.key = this.key;
|
||||||
|
request.userVerificationToken = this.userVerificationToken;
|
||||||
|
await this.apiService.deleteTwoFactorAuthenticator(request);
|
||||||
|
this.enabled = false;
|
||||||
|
this.platformUtilsService.showToast("success", null, this.i18nService.t("twoStepDisabled"));
|
||||||
|
this.onUpdated.emit(false);
|
||||||
|
}
|
||||||
|
|
||||||
private async processResponse(response: TwoFactorAuthenticatorResponse) {
|
private async processResponse(response: TwoFactorAuthenticatorResponse) {
|
||||||
this.formGroup.get("token").setValue(null);
|
this.formGroup.get("token").setValue(null);
|
||||||
this.enabled = response.enabled;
|
this.enabled = response.enabled;
|
||||||
this.key = response.key;
|
this.key = response.key;
|
||||||
|
this.userVerificationToken = response.userVerificationToken;
|
||||||
|
|
||||||
await this.waitForQRiousToLoadOrError().catch((error) => {
|
await this.waitForQRiousToLoadOrError().catch((error) => {
|
||||||
this.logService.error(error);
|
this.logService.error(error);
|
||||||
|
|
|
@ -30,6 +30,7 @@ import {
|
||||||
import { SelectionReadOnlyResponse } from "../admin-console/models/response/selection-read-only.response";
|
import { SelectionReadOnlyResponse } from "../admin-console/models/response/selection-read-only.response";
|
||||||
import { CreateAuthRequest } from "../auth/models/request/create-auth.request";
|
import { CreateAuthRequest } from "../auth/models/request/create-auth.request";
|
||||||
import { DeviceVerificationRequest } from "../auth/models/request/device-verification.request";
|
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";
|
||||||
|
@ -323,6 +324,9 @@ export abstract class ApiService {
|
||||||
putTwoFactorAuthenticator: (
|
putTwoFactorAuthenticator: (
|
||||||
request: UpdateTwoFactorAuthenticatorRequest,
|
request: UpdateTwoFactorAuthenticatorRequest,
|
||||||
) => Promise<TwoFactorAuthenticatorResponse>;
|
) => Promise<TwoFactorAuthenticatorResponse>;
|
||||||
|
deleteTwoFactorAuthenticator: (
|
||||||
|
request: DisableTwoFactorAuthenticatorRequest,
|
||||||
|
) => Promise<TwoFactorProviderResponse>;
|
||||||
putTwoFactorEmail: (request: UpdateTwoFactorEmailRequest) => Promise<TwoFactorEmailResponse>;
|
putTwoFactorEmail: (request: UpdateTwoFactorEmailRequest) => Promise<TwoFactorEmailResponse>;
|
||||||
putTwoFactorDuo: (request: UpdateTwoFactorDuoRequest) => Promise<TwoFactorDuoResponse>;
|
putTwoFactorDuo: (request: UpdateTwoFactorDuoRequest) => Promise<TwoFactorDuoResponse>;
|
||||||
putTwoFactorOrganizationDuo: (
|
putTwoFactorOrganizationDuo: (
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { TwoFactorProviderRequest } from "./two-factor-provider.request";
|
||||||
|
|
||||||
|
export class DisableTwoFactorAuthenticatorRequest extends TwoFactorProviderRequest {
|
||||||
|
key: string;
|
||||||
|
userVerificationToken: string;
|
||||||
|
}
|
|
@ -3,4 +3,5 @@ import { SecretVerificationRequest } from "./secret-verification.request";
|
||||||
export class UpdateTwoFactorAuthenticatorRequest extends SecretVerificationRequest {
|
export class UpdateTwoFactorAuthenticatorRequest extends SecretVerificationRequest {
|
||||||
token: string;
|
token: string;
|
||||||
key: string;
|
key: string;
|
||||||
|
userVerificationToken: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@ import { BaseResponse } from "../../../models/response/base.response";
|
||||||
export class TwoFactorAuthenticatorResponse extends BaseResponse {
|
export class TwoFactorAuthenticatorResponse extends BaseResponse {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
key: string;
|
key: string;
|
||||||
|
userVerificationToken: string;
|
||||||
|
|
||||||
constructor(response: any) {
|
constructor(response: any) {
|
||||||
super(response);
|
super(response);
|
||||||
this.enabled = this.getResponseProperty("Enabled");
|
this.enabled = this.getResponseProperty("Enabled");
|
||||||
this.key = this.getResponseProperty("Key");
|
this.key = this.getResponseProperty("Key");
|
||||||
|
this.userVerificationToken = this.getResponseProperty("UserVerificationToken");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ export enum FeatureFlag {
|
||||||
VaultBulkManagementAction = "vault-bulk-management-action",
|
VaultBulkManagementAction = "vault-bulk-management-action",
|
||||||
AC2828_ProviderPortalMembersPage = "AC-2828_provider-portal-members-page",
|
AC2828_ProviderPortalMembersPage = "AC-2828_provider-portal-members-page",
|
||||||
DeviceTrustLogging = "pm-8285-device-trust-logging",
|
DeviceTrustLogging = "pm-8285-device-trust-logging",
|
||||||
|
AuthenticatorTwoFactorToken = "authenticator-2fa-token",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AllowedFeatureFlagTypes = boolean | number | string;
|
export type AllowedFeatureFlagTypes = boolean | number | string;
|
||||||
|
@ -64,6 +65,7 @@ export const DefaultFeatureFlagValue = {
|
||||||
[FeatureFlag.VaultBulkManagementAction]: FALSE,
|
[FeatureFlag.VaultBulkManagementAction]: FALSE,
|
||||||
[FeatureFlag.AC2828_ProviderPortalMembersPage]: FALSE,
|
[FeatureFlag.AC2828_ProviderPortalMembersPage]: FALSE,
|
||||||
[FeatureFlag.DeviceTrustLogging]: FALSE,
|
[FeatureFlag.DeviceTrustLogging]: FALSE,
|
||||||
|
[FeatureFlag.AuthenticatorTwoFactorToken]: FALSE,
|
||||||
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
} satisfies Record<FeatureFlag, AllowedFeatureFlagTypes>;
|
||||||
|
|
||||||
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
export type DefaultFeatureFlagValueType = typeof DefaultFeatureFlagValue;
|
||||||
|
|
|
@ -37,6 +37,7 @@ import { SelectionReadOnlyResponse } from "../admin-console/models/response/sele
|
||||||
import { TokenService } from "../auth/abstractions/token.service";
|
import { TokenService } from "../auth/abstractions/token.service";
|
||||||
import { CreateAuthRequest } from "../auth/models/request/create-auth.request";
|
import { CreateAuthRequest } from "../auth/models/request/create-auth.request";
|
||||||
import { DeviceVerificationRequest } from "../auth/models/request/device-verification.request";
|
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";
|
||||||
|
@ -998,6 +999,13 @@ export class ApiService implements ApiServiceAbstraction {
|
||||||
return new TwoFactorAuthenticatorResponse(r);
|
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> {
|
async putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise<TwoFactorEmailResponse> {
|
||||||
const r = await this.send("PUT", "/two-factor/email", request, true, true);
|
const r = await this.send("PUT", "/two-factor/email", request, true, true);
|
||||||
return new TwoFactorEmailResponse(r);
|
return new TwoFactorEmailResponse(r);
|
||||||
|
|
Loading…
Reference in New Issue