Skip to content

Commit 9f77110

Browse files
committed
feat(mfa): hide the primary passkey button when MFA is enforced
Also wires config.is_mfa_enforced through AuthorizerConfig / AuthorizerContextPropsType and both default config objects in AuthorizerContext - the field existed in the linked SDK's Meta type but was never declared on the local config types, so referencing it failed to typecheck.
1 parent 8810ebe commit 9f77110

3 files changed

Lines changed: 21 additions & 1 deletion

File tree

src/components/AuthorizerPasskeyLogin.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ export const AuthorizerPasskeyLogin: FC<{
4747
const [loading, setLoading] = useState(false);
4848
const { setAuthData, config, authorizerRef } = useAuthorizer();
4949

50-
if (!isWebauthnSupported()) {
50+
// When the org enforces MFA, passkey must never be offered as a
51+
// standalone primary-login path - it would let a user skip the org's
52+
// two-factor requirement entirely. The server refuses this independently
53+
// (webauthn_login_verify checks EnforceMFA itself), but the button
54+
// shouldn't invite the attempt in the first place: authenticator methods
55+
// belong after a first factor has identified the user, not before.
56+
if (!isWebauthnSupported() || config.is_mfa_enforced) {
5157
return null;
5258
}
5359

@@ -94,6 +100,16 @@ export const AuthorizerPasskeyLogin: FC<{
94100
}
95101
return;
96102
}
103+
if (res && !res.access_token) {
104+
// Reachable only if this button somehow rendered despite the
105+
// is_mfa_enforced guard above (e.g. a brief pre-config-load
106+
// window) - the server is the real boundary and just refused to
107+
// issue a token. Don't treat this as a successful login.
108+
setError(
109+
`Additional verification is required. Please sign in with your email and password instead.`
110+
);
111+
return;
112+
}
97113
if (res) {
98114
setAuthData({
99115
user: res.user || null,

src/contexts/AuthorizerContext.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const AuthorizerContext = createContext<AuthorizerContextPropsType>({
3939
is_multi_factor_auth_enabled: false,
4040
is_mobile_basic_authentication_enabled: false,
4141
is_phone_verification_enabled: false,
42+
is_mfa_enforced: false,
4243
},
4344
configLoadError: null,
4445
user: null,
@@ -114,6 +115,7 @@ let initialState: AuthorizerState = {
114115
is_multi_factor_auth_enabled: false,
115116
is_mobile_basic_authentication_enabled: false,
116117
is_phone_verification_enabled: false,
118+
is_mfa_enforced: false,
117119
},
118120
};
119121

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type AuthorizerConfig = {
2222
is_multi_factor_auth_enabled: boolean;
2323
is_mobile_basic_authentication_enabled: boolean;
2424
is_phone_verification_enabled: boolean;
25+
is_mfa_enforced: boolean;
2526
};
2627

2728
export type AuthorizerState = {
@@ -59,6 +60,7 @@ export type AuthorizerContextPropsType = {
5960
is_multi_factor_auth_enabled: boolean;
6061
is_mobile_basic_authentication_enabled: boolean;
6162
is_phone_verification_enabled: boolean;
63+
is_mfa_enforced: boolean;
6264
};
6365
user: null | User;
6466
token: null | AuthToken;

0 commit comments

Comments
 (0)