From 8da84e61dfe7382a6a862a4984561642ab780a00 Mon Sep 17 00:00:00 2001
From: Aleksander <170264518+t-aleksander@users.noreply.github.com>
Date: Tue, 20 Oct 2026 13:21:52 +0200
Subject: [PATCH 1/3] move fido code
---
.../ConfigureSelectMethodsStep.tsx | 5 +++++
.../components/MethodRow.tsx | 9 +++++++-
new-ui/src/shared/utils/mfa.test.ts | 22 +++++++++++++++++++
new-ui/src/shared/utils/mfa.ts | 13 +++++++++++
src-tauri/Cargo.toml | 4 ++--
src-tauri/deny.toml | 6 ++---
src-tauri/{ => enterprise}/fido2/Cargo.toml | 2 +-
src-tauri/{ => enterprise}/fido2/src/hid.rs | 0
src-tauri/{ => enterprise}/fido2/src/lib.rs | 0
.../{ => enterprise}/fido2/src/protocol.rs | 0
.../fido2/src/protocol/tests.rs | 0
.../{ => enterprise}/fido2/src/windows/api.rs | 0
.../fido2/src/windows/convert.rs | 0
.../{ => enterprise}/fido2/src/windows/mod.rs | 0
.../fido2/src/windows/options.rs | 0
15 files changed, 54 insertions(+), 7 deletions(-)
rename src-tauri/{ => enterprise}/fido2/Cargo.toml (97%)
rename src-tauri/{ => enterprise}/fido2/src/hid.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/lib.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/protocol.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/protocol/tests.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/windows/api.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/windows/convert.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/windows/mod.rs (100%)
rename src-tauri/{ => enterprise}/fido2/src/windows/options.rs (100%)
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx
index 9a9ed86cf..8dd77e023 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx
@@ -19,6 +19,7 @@ import {
isClientConfigurableMethod,
isDesktopDrivableMethod,
isMfaMethodAvailable,
+ isMfaMethodLicenseLocked,
mfaStepsOf as locationMfaSteps,
mfaToText,
setupMethodsOf,
@@ -103,10 +104,13 @@ export const ConfigureSelectMethodsStep = ({ onCancel }: Props) => {
const configured = accountConfigured.includes(method);
const available = isMfaMethodAvailable(method, instance);
const satisfied = configuredMethods.includes(method) && available;
+ const locked = isMfaMethodLicenseLocked(method, instance);
let hint: string | null = null;
if (!available) {
hint = `${mfaToText(method, instance ?? undefined)} is not available on this Defguard instance.`;
+ } else if (locked) {
+ hint = `${mfaToText(method)} requires an Enterprise license on this Defguard instance.`;
} else if (disabled && !configured) {
if (satisfied) {
// Reached only via the email fallback, which registers the factor as it verifies.
@@ -128,6 +132,7 @@ export const ConfigureSelectMethodsStep = ({ onCancel }: Props) => {
disabled,
configured,
hint,
+ locked,
};
},
[accountConfigured, configuredMethods, setupMethods, selected, instance],
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx
index 80a099be7..21c52becc 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx
@@ -19,6 +19,8 @@ export type MethodRowState = {
configured: boolean;
/** Why the row is disabled, when a badge does not already say it. */
hint: string | null;
+ /** The instance license does not allow the factor, so the hint shows a lock. */
+ locked: boolean;
};
interface Props extends MethodRowState {
@@ -31,6 +33,7 @@ export const MethodRow = ({
disabled,
configured,
hint,
+ locked,
onToggle,
}: Props) => (
@@ -52,7 +55,11 @@ export const MethodRow = ({
{isPresent(hint) && (
-
+
{hint}
diff --git a/new-ui/src/shared/utils/mfa.test.ts b/new-ui/src/shared/utils/mfa.test.ts
index 89d453ed2..99898f4a3 100644
--- a/new-ui/src/shared/utils/mfa.test.ts
+++ b/new-ui/src/shared/utils/mfa.test.ts
@@ -15,6 +15,7 @@ import {
connectionAbilityOf,
hasMfaMethodChoice,
isMfaMethodAvailable,
+ isMfaMethodLicenseLocked,
mfaConfigurableInstances,
resolveMfaStepPlan,
setupMethodsOf,
@@ -122,6 +123,27 @@ describe('setupMethodsOf', () => {
});
});
+describe('isMfaMethodLicenseLocked', () => {
+ it('locks FIDO2 when Core leaves it out of the setup methods', () => {
+ const instance = {
+ mfa_capabilities: capabilitiesOf([MfaMethod.Totp, MfaMethod.Email]),
+ };
+ expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, instance)).toBe(true);
+ expect(isMfaMethodLicenseLocked(MfaMethod.Totp, instance)).toBe(false);
+ });
+
+ it('does not lock FIDO2 when Core offers it or cannot configure from the client', () => {
+ const offered = {
+ mfa_capabilities: capabilitiesOf([MfaMethod.Totp, MfaMethod.Fido2]),
+ };
+ expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, offered)).toBe(false);
+ expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, { mfa_capabilities: null })).toBe(
+ false,
+ );
+ expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, undefined)).toBe(false);
+ });
+});
+
describe('canSetUpMfaMethod', () => {
it('needs both the client and the instance', () => {
const instance = {
diff --git a/new-ui/src/shared/utils/mfa.ts b/new-ui/src/shared/utils/mfa.ts
index ca5e51cd9..a61cab5d4 100644
--- a/new-ui/src/shared/utils/mfa.ts
+++ b/new-ui/src/shared/utils/mfa.ts
@@ -208,6 +208,19 @@ export const canSetUpMfaMethod = (
): method is ClientConfigurableMethod =>
setupMethodsOf(instance).some((candidate) => candidate === method);
+/** Core leaves FIDO2 out of the setup methods when its license lacks the Enterprise tier. */
+export const isMfaMethodLicenseLocked = (
+ method: MfaMethodValue,
+ instance?: Pick | null,
+): boolean => {
+ const coreSetupMethods = instance?.mfa_capabilities?.setup_methods;
+ return (
+ method === MfaMethod.Fido2 &&
+ isPresent(coreSetupMethods) &&
+ !coreSetupMethods.includes(method)
+ );
+};
+
/** What this client can authorize an MFA configuration session with. Mirrors
* AUTHORIZING_METHODS in core mfa_config.rs. */
const clientAuthorizingMethods: MfaMethodValue[] = [
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 1ca4b7b85..8c91a7894 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
-members = ["cli", "client-cli", "common", "client-proto", "core", "daemon", "fido2", "enterprise/posture", "enterprise/provisioning", "enterprise/config-sync", "enterprise/service-locations"]
+members = ["cli", "client-cli", "common", "client-proto", "core", "daemon", "enterprise/fido2", "enterprise/posture", "enterprise/provisioning", "enterprise/config-sync", "enterprise/service-locations"]
default-members = ["cli", "client-cli", "daemon", "."]
[workspace.dependencies]
@@ -131,7 +131,7 @@ redundant_closure = "warn"
base64.workspace = true
chrono.workspace = true
defguard-cli.path = "client-cli"
-defguard-client-fido2.path = "fido2"
+defguard-client-fido2.path = "enterprise/fido2"
defguard-client-proto.path = "client-proto"
defguard-client-core.path = "core"
defguard-client-posture.path = "enterprise/posture"
diff --git a/src-tauri/deny.toml b/src-tauri/deny.toml
index aa2b73fbc..65b8f7003 100644
--- a/src-tauri/deny.toml
+++ b/src-tauri/deny.toml
@@ -144,9 +144,6 @@ exceptions = [
{ allow = [
"AGPL-3.0-or-later",
], crate = "defguard-client-core" },
- { allow = [
- "AGPL-3.0-or-later",
- ], crate = "defguard-client-fido2" },
{ allow = [
"AGPL-3.0-or-later",
], crate = "defguard-client-service" },
@@ -168,6 +165,9 @@ exceptions = [
{ allow = [
"LicenseRef-Proprietary",
], crate = "defguard-client-service-locations" },
+ { allow = [
+ "LicenseRef-Proprietary",
+ ], crate = "defguard-client-fido2" },
]
# Some crates don't have (easily) machine readable licensing information,
diff --git a/src-tauri/fido2/Cargo.toml b/src-tauri/enterprise/fido2/Cargo.toml
similarity index 97%
rename from src-tauri/fido2/Cargo.toml
rename to src-tauri/enterprise/fido2/Cargo.toml
index d37be7abc..1ff3cf7ef 100644
--- a/src-tauri/fido2/Cargo.toml
+++ b/src-tauri/enterprise/fido2/Cargo.toml
@@ -4,7 +4,7 @@ description = "FIDO2 security key ceremonies for the Defguard desktop client (Ta
authors.workspace = true
edition.workspace = true
homepage.workspace = true
-license-file.workspace = true
+license = "LicenseRef-Proprietary"
rust-version.workspace = true
version.workspace = true
diff --git a/src-tauri/fido2/src/hid.rs b/src-tauri/enterprise/fido2/src/hid.rs
similarity index 100%
rename from src-tauri/fido2/src/hid.rs
rename to src-tauri/enterprise/fido2/src/hid.rs
diff --git a/src-tauri/fido2/src/lib.rs b/src-tauri/enterprise/fido2/src/lib.rs
similarity index 100%
rename from src-tauri/fido2/src/lib.rs
rename to src-tauri/enterprise/fido2/src/lib.rs
diff --git a/src-tauri/fido2/src/protocol.rs b/src-tauri/enterprise/fido2/src/protocol.rs
similarity index 100%
rename from src-tauri/fido2/src/protocol.rs
rename to src-tauri/enterprise/fido2/src/protocol.rs
diff --git a/src-tauri/fido2/src/protocol/tests.rs b/src-tauri/enterprise/fido2/src/protocol/tests.rs
similarity index 100%
rename from src-tauri/fido2/src/protocol/tests.rs
rename to src-tauri/enterprise/fido2/src/protocol/tests.rs
diff --git a/src-tauri/fido2/src/windows/api.rs b/src-tauri/enterprise/fido2/src/windows/api.rs
similarity index 100%
rename from src-tauri/fido2/src/windows/api.rs
rename to src-tauri/enterprise/fido2/src/windows/api.rs
diff --git a/src-tauri/fido2/src/windows/convert.rs b/src-tauri/enterprise/fido2/src/windows/convert.rs
similarity index 100%
rename from src-tauri/fido2/src/windows/convert.rs
rename to src-tauri/enterprise/fido2/src/windows/convert.rs
diff --git a/src-tauri/fido2/src/windows/mod.rs b/src-tauri/enterprise/fido2/src/windows/mod.rs
similarity index 100%
rename from src-tauri/fido2/src/windows/mod.rs
rename to src-tauri/enterprise/fido2/src/windows/mod.rs
diff --git a/src-tauri/fido2/src/windows/options.rs b/src-tauri/enterprise/fido2/src/windows/options.rs
similarity index 100%
rename from src-tauri/fido2/src/windows/options.rs
rename to src-tauri/enterprise/fido2/src/windows/options.rs
From 1864aa49669e596ff9c9d7a7dd76a910076a3957 Mon Sep 17 00:00:00 2001
From: Aleksander <170264518+t-aleksander@users.noreply.github.com>
Date: Thu, 22 Oct 2026 12:51:47 +0200
Subject: [PATCH 2/3] make labels more generic
---
.../ConfigureSelectMethodsStep.tsx | 8 +++----
.../components/MethodRow.tsx | 2 +-
new-ui/src/shared/utils/mfa.test.ts | 22 ++++++++++++-------
new-ui/src/shared/utils/mfa.ts | 9 +++++---
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx
index 8dd77e023..d447ec097 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/ConfigureSelectMethodsStep.tsx
@@ -19,7 +19,7 @@ import {
isClientConfigurableMethod,
isDesktopDrivableMethod,
isMfaMethodAvailable,
- isMfaMethodLicenseLocked,
+ isMfaMethodLocked,
mfaStepsOf as locationMfaSteps,
mfaToText,
setupMethodsOf,
@@ -104,13 +104,11 @@ export const ConfigureSelectMethodsStep = ({ onCancel }: Props) => {
const configured = accountConfigured.includes(method);
const available = isMfaMethodAvailable(method, instance);
const satisfied = configuredMethods.includes(method) && available;
- const locked = isMfaMethodLicenseLocked(method, instance);
+ const locked = isMfaMethodLocked(method, instance);
let hint: string | null = null;
- if (!available) {
+ if (!available || locked) {
hint = `${mfaToText(method, instance ?? undefined)} is not available on this Defguard instance.`;
- } else if (locked) {
- hint = `${mfaToText(method)} requires an Enterprise license on this Defguard instance.`;
} else if (disabled && !configured) {
if (satisfied) {
// Reached only via the email fallback, which registers the factor as it verifies.
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx
index 21c52becc..def4bc336 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectMethodsStep/components/MethodRow.tsx
@@ -19,7 +19,7 @@ export type MethodRowState = {
configured: boolean;
/** Why the row is disabled, when a badge does not already say it. */
hint: string | null;
- /** The instance license does not allow the factor, so the hint shows a lock. */
+ /** The instance withholds the factor, so the hint shows a lock. */
locked: boolean;
};
diff --git a/new-ui/src/shared/utils/mfa.test.ts b/new-ui/src/shared/utils/mfa.test.ts
index 99898f4a3..641efb25c 100644
--- a/new-ui/src/shared/utils/mfa.test.ts
+++ b/new-ui/src/shared/utils/mfa.test.ts
@@ -15,7 +15,7 @@ import {
connectionAbilityOf,
hasMfaMethodChoice,
isMfaMethodAvailable,
- isMfaMethodLicenseLocked,
+ isMfaMethodLocked,
mfaConfigurableInstances,
resolveMfaStepPlan,
setupMethodsOf,
@@ -123,24 +123,30 @@ describe('setupMethodsOf', () => {
});
});
-describe('isMfaMethodLicenseLocked', () => {
- it('locks FIDO2 when Core leaves it out of the setup methods', () => {
+describe('isMfaMethodLocked', () => {
+ it('locks a client-configurable method Core leaves out of the setup methods', () => {
const instance = {
mfa_capabilities: capabilitiesOf([MfaMethod.Totp, MfaMethod.Email]),
};
- expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, instance)).toBe(true);
- expect(isMfaMethodLicenseLocked(MfaMethod.Totp, instance)).toBe(false);
+ expect(isMfaMethodLocked(MfaMethod.Fido2, instance)).toBe(true);
+ expect(isMfaMethodLocked(MfaMethod.Totp, instance)).toBe(false);
+ expect(isMfaMethodLocked(MfaMethod.Oidc, instance)).toBe(false);
+
+ const withoutTotp = {
+ mfa_capabilities: capabilitiesOf([MfaMethod.Email, MfaMethod.Fido2]),
+ };
+ expect(isMfaMethodLocked(MfaMethod.Totp, withoutTotp)).toBe(true);
});
it('does not lock FIDO2 when Core offers it or cannot configure from the client', () => {
const offered = {
mfa_capabilities: capabilitiesOf([MfaMethod.Totp, MfaMethod.Fido2]),
};
- expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, offered)).toBe(false);
- expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, { mfa_capabilities: null })).toBe(
+ expect(isMfaMethodLocked(MfaMethod.Fido2, offered)).toBe(false);
+ expect(isMfaMethodLocked(MfaMethod.Fido2, { mfa_capabilities: null })).toBe(
false,
);
- expect(isMfaMethodLicenseLocked(MfaMethod.Fido2, undefined)).toBe(false);
+ expect(isMfaMethodLocked(MfaMethod.Fido2, undefined)).toBe(false);
});
});
diff --git a/new-ui/src/shared/utils/mfa.ts b/new-ui/src/shared/utils/mfa.ts
index a61cab5d4..79584a6b0 100644
--- a/new-ui/src/shared/utils/mfa.ts
+++ b/new-ui/src/shared/utils/mfa.ts
@@ -208,14 +208,17 @@ export const canSetUpMfaMethod = (
): method is ClientConfigurableMethod =>
setupMethodsOf(instance).some((candidate) => candidate === method);
-/** Core leaves FIDO2 out of the setup methods when its license lacks the Enterprise tier. */
-export const isMfaMethodLicenseLocked = (
+/**
+ * Every Core that reports capabilities knows all client-configurable methods, so one it leaves out
+ * of the setup methods is withheld from this instance.
+ */
+export const isMfaMethodLocked = (
method: MfaMethodValue,
instance?: Pick | null,
): boolean => {
const coreSetupMethods = instance?.mfa_capabilities?.setup_methods;
return (
- method === MfaMethod.Fido2 &&
+ isClientConfigurableMethod(method) &&
isPresent(coreSetupMethods) &&
!coreSetupMethods.includes(method)
);
From edf06f524f3c1d9e95606b22200b64dd6768895c Mon Sep 17 00:00:00 2001
From: Aleksander <170264518+t-aleksander@users.noreply.github.com>
Date: Thu, 22 Oct 2026 12:56:08 +0200
Subject: [PATCH 3/3] merge two lists
---
.../hooks/useConfigureMfaStore.tsx | 18 ++++++++----------
.../src/pages/full/ConfigureMfaPage/types.ts | 12 +-----------
.../src/pages/full/ConfigureMfaPage/utils.ts | 10 +++++-----
.../verify/ConfigureMfaVerify.tsx | 4 ++--
.../ConfigureSelectVerificationStep.tsx | 6 ++++--
new-ui/src/shared/utils/mfa.ts | 12 +++++++-----
6 files changed, 27 insertions(+), 35 deletions(-)
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/hooks/useConfigureMfaStore.tsx b/new-ui/src/pages/full/ConfigureMfaPage/hooks/useConfigureMfaStore.tsx
index fdf06de92..092ba1920 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/hooks/useConfigureMfaStore.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/hooks/useConfigureMfaStore.tsx
@@ -13,14 +13,12 @@ import {
type MfaMethodValue,
} from '../../../../shared/rust-api/types';
import { isPresent } from '../../../../shared/utils/isPresent';
-import { setupMethodsOf } from '../../../../shared/utils/mfa';
-import { dismissEdgeComsError } from '../components/EdgeComsError/useEdgeComsErrorStore';
import {
- ConfigureMfaStep,
- type ConfigureMfaStepValue,
- MFA_WIZARD_STEPS,
- type MfaVerificationMethod,
-} from '../types';
+ type ClientAuthorizingMethod,
+ setupMethodsOf,
+} from '../../../../shared/utils/mfa';
+import { dismissEdgeComsError } from '../components/EdgeComsError/useEdgeComsErrorStore';
+import { ConfigureMfaStep, type ConfigureMfaStepValue, MFA_WIZARD_STEPS } from '../types';
import {
isCodeMfaMethod,
isMfaFactorOfferable,
@@ -45,9 +43,9 @@ type StoreValues = {
/** Pre-ticked in the selection step, from the entry point or an earlier pass. */
initialSelection: MfaMethodValue[];
/** most preferred first, from the session since an older Core rejects some factors */
- verificationMethods: MfaVerificationMethod[];
+ verificationMethods: ClientAuthorizingMethod[];
/** null until picked, asked only when the session offers more than one method */
- verificationMethod: MfaVerificationMethod | null;
+ verificationMethod: ClientAuthorizingMethod | null;
/** No factor was configured, so an emailed code was the only way in. */
emailFallback: boolean;
/** ISO timestamp the session dies at, null once nothing in the flow needs it. */
@@ -136,7 +134,7 @@ interface Store extends StoreValues {
origin: ConfigureMfaOrigin,
) => void;
selectMethods: (methods: MfaMethodValue[]) => void;
- selectVerificationMethod: (method: MfaVerificationMethod) => void;
+ selectVerificationMethod: (method: ClientAuthorizingMethod) => void;
/** Keeps the current picks ticked and the session alive. */
backToSelection: () => void;
backFromVerification: () => void;
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/types.ts b/new-ui/src/pages/full/ConfigureMfaPage/types.ts
index 3be9ef2ba..7f6ac7614 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/types.ts
+++ b/new-ui/src/pages/full/ConfigureMfaPage/types.ts
@@ -1,4 +1,4 @@
-import { MfaMethod, type MfaMethodValue } from '../../../shared/rust-api/types';
+import type { MfaMethodValue } from '../../../shared/rust-api/types';
/** Wizard steps, in the order they run. Setup steps are the ones a factor can claim. */
export const ConfigureMfaStep = {
@@ -25,13 +25,3 @@ export type MfaFactor = {
/** Whether the account can hold several of these, so it stays offerable once configured. */
repeatable: boolean;
};
-
-/** most preferred first */
-export const mfaVerificationMethods = [
- MfaMethod.Totp,
- MfaMethod.Email,
- MfaMethod.Fido2,
- MfaMethod.Oidc,
-] as const;
-
-export type MfaVerificationMethod = (typeof mfaVerificationMethods)[number];
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/utils.ts b/new-ui/src/pages/full/ConfigureMfaPage/utils.ts
index e0fe944d5..254332a76 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/utils.ts
+++ b/new-ui/src/pages/full/ConfigureMfaPage/utils.ts
@@ -4,7 +4,9 @@ import {
type MfaMethodValue,
} from '../../../shared/rust-api/types';
import {
+ CLIENT_AUTHORIZING_METHODS,
CLIENT_CONFIGURABLE_METHODS,
+ type ClientAuthorizingMethod,
type ClientConfigurableMethod,
} from '../../../shared/utils/mfa';
import {
@@ -12,8 +14,6 @@ import {
type ConfigureMfaStepValue,
MFA_WIZARD_STEPS,
type MfaFactor,
- type MfaVerificationMethod,
- mfaVerificationMethods,
} from './types';
/** Keyed on the shared list, so a new factor fails to compile until mapped here. */
@@ -64,13 +64,13 @@ export const isCodeMfaMethod = (method: MfaMethodValue): boolean =>
/** ordered by preference, not by the input */
export const verificationMethodsOf = (
availableMethods: MfaMethodValue[],
-): MfaVerificationMethod[] =>
- mfaVerificationMethods.filter((method) => availableMethods.includes(method));
+): ClientAuthorizingMethod[] =>
+ CLIENT_AUTHORIZING_METHODS.filter((method) => availableMethods.includes(method));
/** The fallback mails a code to the address on file, so email is the only way in. */
export const sessionVerificationMethodsOf = (
response: Pick,
-): MfaVerificationMethod[] =>
+): ClientAuthorizingMethod[] =>
verificationMethodsOf(
response.email_fallback ? [MfaMethod.Email] : response.available_methods,
);
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureMfaVerify.tsx b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureMfaVerify.tsx
index 6b54141e4..0b1b70cce 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureMfaVerify.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureMfaVerify.tsx
@@ -1,7 +1,7 @@
import { MfaMethod } from '../../../../shared/rust-api/types';
import { isPresent } from '../../../../shared/utils/isPresent';
+import type { ClientAuthorizingMethod } from '../../../../shared/utils/mfa';
import { useConfigureMfaStore } from '../hooks/useConfigureMfaStore';
-import type { MfaVerificationMethod } from '../types';
import { ConfigureSelectMethodsStep } from './ConfigureSelectMethodsStep/ConfigureSelectMethodsStep';
import { ConfigureSelectVerificationStep } from './ConfigureSelectVerificationStep/ConfigureSelectVerificationStep';
import { ConfigureVerifyEmailStep } from './ConfigureVerifyEmailStep/ConfigureVerifyEmailStep';
@@ -29,7 +29,7 @@ export const ConfigureMfaVerify = ({ onCancel, onSessionExpired }: Props) => {
}
// for the type only, a session with nothing to verify with is refused at start
- const method: MfaVerificationMethod =
+ const method: ClientAuthorizingMethod =
verificationMethod ?? candidates[0] ?? MfaMethod.Email;
switch (method) {
diff --git a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectVerificationStep/ConfigureSelectVerificationStep.tsx b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectVerificationStep/ConfigureSelectVerificationStep.tsx
index 891111769..3d4fbe723 100644
--- a/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectVerificationStep/ConfigureSelectVerificationStep.tsx
+++ b/new-ui/src/pages/full/ConfigureMfaPage/verify/ConfigureSelectVerificationStep/ConfigureSelectVerificationStep.tsx
@@ -4,9 +4,9 @@ import { ButtonVariant } from '../../../../../shared/components/Button/types';
import { Controls } from '../../../../../shared/components/Controls/Controls';
import { FullPageTitle } from '../../../../../shared/components/FullPageTitle/FullPageTitle';
import { FullPage } from '../../../../../shared/layouts/FullPage/FullPage';
+import type { ClientAuthorizingMethod } from '../../../../../shared/utils/mfa';
import { ConfigureMfaVerificatorFactorSelector } from '../../components/ConfigureMfaVerificatorFactorSelector/ConfigureMfaVerificatorFactorSelector';
import { useConfigureMfaStore } from '../../hooks/useConfigureMfaStore';
-import type { MfaVerificationMethod } from '../../types';
import '../style.scss';
import './style.scss';
@@ -14,7 +14,9 @@ import './style.scss';
export const ConfigureSelectVerificationStep = () => {
const methods = useConfigureMfaStore((s) => s.verificationMethods);
- const [selected, setSelected] = useState(methods[0]);
+ const [selected, setSelected] = useState(
+ methods[0],
+ );
return (
&
MfaCapabilitiesInstance;
@@ -243,7 +245,7 @@ export type MfaConfigInstance = Pick &
export const canAuthorizeMfaConfig = (instance?: MfaConfigInstance | null): boolean => {
const authorizeMethods = instance?.mfa_capabilities?.authorize_methods ?? [];
const configuredMethods = instance?.mfa_configured_methods ?? [];
- const holdsAuthorizer = clientAuthorizingMethods.some(
+ const holdsAuthorizer = CLIENT_AUTHORIZING_METHODS.some(
(method) =>
authorizeMethods.includes(method) &&
configuredMethods.includes(method) &&