WebAuthn设userVerification为preferred时遇超时/权限错误的解决问询
Troubleshooting WebAuthn
userVerification: "preferred" Errors Immediate Fix: Error-Driven Fallback Flow
The most practical way to keep userVerification: "preferred" while avoiding timeout/permission errors is to implement a retry mechanism that falls back to "discouraged" only when the specific error occurs. This preserves compatibility with services like Google that require higher UV settings, while accommodating devices that struggle with preferred mode.
Here’s a code example for passkey registration:
async function registerPasskey(originalOptions) { const baseOptions = { ...originalOptions.publicKey }; try { // First attempt with preferred user verification return await navigator.credentials.create({ publicKey: { ...baseOptions, userVerification: "preferred" } }); } catch (err) { // Trigger fallback only for the target error if (err.message.includes("timed out or was not allowed")) { return await navigator.credentials.create({ publicKey: { ...baseOptions, userVerification: "discouraged" } }); } // Re-throw other errors to handle them separately throw err; } }
Known Compatibility Issues
Several device/browser combinations are known to exhibit this behavior with userVerification: "preferred":
- Older Android devices (pre-13): Third-party security keys or inconsistent biometric support can lead to UV request failures.
- macOS Safari pre-Ventura (13.0): Touch ID prompts often timed out due to browser-level bugs.
- Linux browsers (older Firefox/Chrome): Some security keys don’t properly respond to UV requests, resulting in permission errors.
- Windows Hello on older Windows 10 builds: Inconsistent handling of preferred UV can cause timeouts if biometrics aren’t immediately accessible.
Additional Mitigations
- Clear User Instructions: When initiating a flow with
preferred, display explicit UI cues (e.g., "Scan your face" or "Touch the security key") to prevent user confusion and timeouts. - Honor RP-Specified UV Settings: If the request comes from a relying party (like Google) that explicitly requires
"preferred"or"required", skip the fallback—only apply it to your service’s default flows. - Detect Authenticator Capabilities: While not 100% reliable, you can use a dummy
get()request to check UV support before setting the level:async function supportsUserVerification() { try { await navigator.credentials.get({ publicKey: { challenge: new Uint8Array(32), allowCredentials: [], userVerification: "required" } }); return true; } catch (err) { return false; } }
Long-Term Best Practices
- Keep browser and OS versions updated: Most UV-related bugs are patched in newer releases.
- Test across authenticators: Validate with Touch ID, Face ID, YubiKey, and Android Biometrics to identify edge cases.
- Document user workarounds: For known problematic devices, inform users to ensure their biometrics/security keys are properly set up before initiating the flow.
内容的提问来源于stack exchange,提问作者loxeso3659
相关产品推荐
相关产品推荐

