The WebAuthn ‘prf / hmac-secret extension unsupported’ error occurs when a passkey smart wallet attempts to derive deterministic cryptographic seeds from a device authenticator that does not support the FIDO2.1 PRF extension. While Apple Keychain (iOS 17.4+) and Google Password Manager support PRF, older operating systems, hardware keys (YubiKey 5 without PRF), or third-party managers reject the request. Implementing fallback asymmetric signature schemes bypasses the failure.
Before executing state changes or signing transactions, verify your cryptographic parameters using our interactive WebAuthn Passkey Debugger utility.
Why PRF Fails: The Triad Compatibility Gap
For WebAuthn PRF to function, three distinct software and hardware layers must all support it concurrently:
flowchart LR
A["Browser Engine\n(WebAuthn Level 3)"] --> B["Operating System / Platform\n(Passkey Provider)"]
B --> C["Hardware Security Enclave\n(CTAP 2.1 hmac-secret)"]
If any single link in this chain is missing, the derivation fails silently:
- Browser Layer: While Chrome 116+ and Safari 17.4+ support PRF, Mozilla Firefox currently does not support the PRF extension. Users logging into a Web3 dApp via Firefox receive
credential.getClientExtensionResults().prf === undefined. - Platform Layer: Windows Hello on Windows 10/11 supports PRF, and macOS Sonoma/Sequoia supports PRF on iCloud Keychain passkeys. However, Chromium on Linux desktop distributions generally lacks platform PRF support unless connected to a modern hardware security key.
- Hardware Roaming Authenticators: If the user selects a physical FIDO2 key (e.g. YubiKey 5 Series), it must have firmware version 5.4.3 or higher to support the CTAP 2.1
hmac-secretcommand. Older keys (such as YubiKey 4 or early YubiKey 5) reject or ignore the extension during registration.
Step-by-Step Resolution Architecture
1. Robust Runtime Feature & Capability Detection
Never assume the client browser or authenticator supports PRF. You must probe for capability before attempting cryptographic derivation:
// Detect browser PRF extension capability
export function isPrfSupportedByBrowser(): boolean {
if (typeof window === 'undefined' || !window.PublicKeyCredential) {
return false;
}
// Check if getClientCapabilities exists (Chromium 124+)
if (typeof (PublicKeyCredential as any).getClientCapabilities === 'function') {
// Note: getClientCapabilities is asynchronous in modern standards
return true;
}
// User-Agent heuristic fallback for non-supporting browsers
const ua = navigator.userAgent.toLowerCase();
if (ua.includes('firefox')) {
return false; // Firefox currently omits WebAuthn PRF
}
return true;
}
2. Requesting the PRF Extension with Defensive Options
When creating credentials (navigator.credentials.create) or requesting assertions (navigator.credentials.get), pass the PRF extension structure correctly and expect undefined:
import { bytesToHex, hexToBytes } from 'viem';
// Salt must be exactly 32 bytes (256 bits)
const DAPP_DERIVATION_SALT = new TextEncoder().encode("layerzerofault-auth-v1-salt-32b");
export async function requestPasskeyPrfKey(credentialId: Uint8Array): Promise<Uint8Array | null> {
if (!isPrfSupportedByBrowser()) {
console.warn("Browser lacks PRF extension support. Triggering fallback pathway.");
return null;
}
try {
const assertion = await navigator.credentials.get({
publicKey: {
challenge: crypto.getRandomValues(new Uint8Array(32)),
allowCredentials: [{
id: credentialId,
type: 'public-key',
transports: ['internal', 'hybrid', 'usb'],
}],
userVerification: 'required',
extensions: {
prf: {
eval: {
first: DAPP_DERIVATION_SALT,
},
},
},
},
}) as PublicKeyCredential;
const extensionResults = assertion.getClientExtensionResults();
// Defensive check: extension results may exist without prf
if (!extensionResults.prf || !extensionResults.prf.results || !extensionResults.prf.results.first) {
console.warn("Authenticator omitted PRF output. Authenticator may lack CTAP 2.1 hmac-secret.");
return null;
}
// Successfully extracted 32-byte symmetric seed
const derivedSeed = new Uint8Array(extensionResults.prf.results.first);
return derivedSeed;
} catch (err: any) {
console.error("WebAuthn assertion failed:", err);
return null;
}
}
3. Graceful Fallback: Hybrid MPC / Enclave Key Derivation
When requestPasskeyPrfKey returns null (due to Firefox, Linux, or an older hardware key), your application must not crash. Instead, route the user to a hybrid fallback recovery scheme:
import { decryptWithWebCrypto, requestMpcCloudShare } from './walletFallback';
export async function unlockUserWallet(credentialId: Uint8Array, userAddress: string) {
// 1. Attempt hardware-enclave PRF derivation
const prfSeed = await requestPasskeyPrfKey(credentialId);
if (prfSeed !== null) {
// Happy path: Fast, non-custodial local decryption
const privateKey = await deriveAndDecryptLocalShare(prfSeed, userAddress);
return { privateKey, source: 'hardware_prf' };
}
// 2. Fallback Path: 2-of-3 MPC or Passcode Enclave Recovery
console.info("Engaging multi-party recovery fallback for unsupported PRF environment...");
// Prompt user for their secondary backup factor (e.g. Passcode or Email OTP)
const userPasscode = await promptUserForRecoveryPasscode();
const cloudShare = await requestMpcCloudShare(userAddress, userPasscode);
const localIndexedDbShare = await loadLocalEncryptedShare(userAddress);
const restoredKey = reconstructMpcPrivateKey(cloudShare, localIndexedDbShare);
return { privateKey: restoredKey, source: 'mpc_fallback' };
}
User Communication UX Pattern
When PRF fails due to browser limitations, present a clear, actionable banner rather than an opaque technical error:
Browser Compatibility Notice: Your current browser does not support biometric cryptographic derivation (WebAuthn PRF).
- To enable seamless one-click biometric login, switch to Google Chrome, Microsoft Edge, or Apple Safari 17.4+.
- Alternatively, continue using our Encrypted Cloud Recovery Backup below.
By implementing runtime capability detection alongside a robust 2-of-3 MPC or Shamir fallback, you eliminate passkey wallet lockouts across all platforms while preserving top-tier biometric security for supported users.
[!TIP] Companion Diagnostic Guide: If experiencing related infrastructure failures, cross-reference symptoms with our technical breakdown on WebCrypto P-256 SPKI DER Header Mismatch in Passkey Smart Accounts.