Fix: hide passwordless toggle when disabled, remove lock auto-trigger
1. Passwordless toggle in Settings is now hidden when admin hasn't enabled allow_passwordless in system config (or when user already has it enabled — so they can still disable it). Backend exposes allow_passwordless in /auth/status response. 2. Remove auto-trigger passkey ceremony on lock screen — previously fired immediately when session locked for passwordless users. Now waits for user to click "Unlock with passkey" button. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
42d73526f5
commit
1b868ba503
@ -553,6 +553,7 @@ async def auth_status(
|
||||
"has_passkeys": has_passkeys,
|
||||
"passkey_count": passkey_count,
|
||||
"passwordless_enabled": passwordless_enabled,
|
||||
"allow_passwordless": config.allow_passwordless if config else False,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -39,14 +39,6 @@ export default function LockOverlay() {
|
||||
}
|
||||
}, [isLocked, showPasswordForm]);
|
||||
|
||||
// Auto-trigger passkey unlock when passwordless mode is enabled
|
||||
useEffect(() => {
|
||||
if (isLocked && passwordlessEnabled && supportsWebAuthn && !isPasskeyUnlocking) {
|
||||
handlePasskeyUnlock();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isLocked, passwordlessEnabled]);
|
||||
|
||||
if (!isLocked) return null;
|
||||
|
||||
const preferredName = settings?.preferred_name;
|
||||
|
||||
@ -137,7 +137,7 @@ function PasskeyDeleteButton({ credential, onDelete, isDeleting }: DeleteConfirm
|
||||
|
||||
export default function PasskeySection() {
|
||||
const queryClient = useQueryClient();
|
||||
const { passwordlessEnabled, passkeyCount } = useAuth();
|
||||
const { passwordlessEnabled, passkeyCount, allowPasswordless } = useAuth();
|
||||
|
||||
// Registration state
|
||||
const [registerDialogOpen, setRegisterDialogOpen] = useState(false);
|
||||
@ -376,9 +376,10 @@ export default function PasskeySection() {
|
||||
{hasPasskeys ? 'Add another passkey' : 'Add a passkey'}
|
||||
</Button>
|
||||
|
||||
{/* Passwordless login section */}
|
||||
<Separator />
|
||||
{/* Passwordless login section — hidden when admin hasn't enabled the feature */}
|
||||
{(allowPasswordless || passwordlessEnabled) && <Separator />}
|
||||
|
||||
{(allowPasswordless || passwordlessEnabled) && (
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center gap-2">
|
||||
@ -388,7 +389,7 @@ export default function PasskeySection() {
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Skip the password prompt and unlock the app using a passkey only.
|
||||
</p>
|
||||
{passkeyCount < 2 && (
|
||||
{passkeyCount < 2 && !passwordlessEnabled && (
|
||||
<p className="text-xs text-amber-400">
|
||||
Requires at least 2 registered passkeys as a fallback.
|
||||
</p>
|
||||
@ -409,6 +410,7 @@ export default function PasskeySection() {
|
||||
aria-label="Toggle passwordless login"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Enable passwordless dialog */}
|
||||
<Dialog open={enableDialogOpen} onOpenChange={(open) => {
|
||||
|
||||
@ -154,5 +154,6 @@ export function useAuth() {
|
||||
hasPasskeys: authQuery.data?.has_passkeys ?? false,
|
||||
passkeyCount: authQuery.data?.passkey_count ?? 0,
|
||||
passwordlessEnabled: authQuery.data?.passwordless_enabled ?? false,
|
||||
allowPasswordless: authQuery.data?.allow_passwordless ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -246,6 +246,7 @@ export interface AuthStatus {
|
||||
has_passkeys: boolean;
|
||||
passkey_count: number;
|
||||
passwordless_enabled: boolean;
|
||||
allow_passwordless: boolean;
|
||||
}
|
||||
|
||||
export interface PasskeyCredential {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user