Creates a discoverable, user-verified passkey that requires WebAuthn PRF
support and returns the first PRF output.
@param ― options - Passkey creation inputs.
@returns ― Credential metadata and the first PRF output.
@remarks ―
Runs one creation ceremony and shows one user-verification prompt. On
authenticators that do not evaluate PRF during creation, a fallback
assertion evaluates the same salt and shows a second prompt.
WebAuthn challenges and the credential's user handle (user.id) are
generated internally, 32 random bytes each. An authenticator overwrites a
discoverable credential that has the same rp.id and user.id, so a fresh
handle per call adds a passkey instead of replacing one.
The credential is requested with fixed parameters: ES256 or RS256 key types,
attestation "none", a required resident key, and required user
verification (getPasskeyPrfOutput explains the requirement).
Any failure after the creation ceremony completes leaves the passkey on the
authenticator, but the thrown error does not carry its metadata.
@throws ― MeraError with code PRF_UNAVAILABLE when the authenticator reports no PRF support and returns no create-time output, returns an output that is not 32 bytes, or returns none on the fallback ceremony.
@throws ― MeraError with code INPUT_INVALID when an explicit prfSalt is not 32 bytes.
@throws ― MeraError with code CRYPTO_UNAVAILABLE when crypto.getRandomValues is unavailable.
@throws ― MeraError with code PASSKEY_CANCELLED when the person dismisses a prompt, it times out, or no passkey answers.
@throws ― MeraError with code PASSKEY_OPERATION_FAILED when WebAuthn is unavailable, fails for another reason, or returns an unexpected credential.
Creates a discoverable, user-verified passkey that requires WebAuthn PRF
support and returns the first PRF output.
@param ― options - Passkey creation inputs.
@returns ― Credential metadata and the first PRF output.
@remarks ―
Runs one creation ceremony and shows one user-verification prompt. On
authenticators that do not evaluate PRF during creation, a fallback
assertion evaluates the same salt and shows a second prompt.
WebAuthn challenges and the credential's user handle (user.id) are
generated internally, 32 random bytes each. An authenticator overwrites a
discoverable credential that has the same rp.id and user.id, so a fresh
handle per call adds a passkey instead of replacing one.
The credential is requested with fixed parameters: ES256 or RS256 key types,
attestation "none", a required resident key, and required user
verification (getPasskeyPrfOutput explains the requirement).
Any failure after the creation ceremony completes leaves the passkey on the
authenticator, but the thrown error does not carry its metadata.
@throws ― MeraError with code PRF_UNAVAILABLE when the authenticator reports no PRF support and returns no create-time output, returns an output that is not 32 bytes, or returns none on the fallback ceremony.
@throws ― MeraError with code INPUT_INVALID when an explicit prfSalt is not 32 bytes.
@throws ― MeraError with code CRYPTO_UNAVAILABLE when crypto.getRandomValues is unavailable.
@throws ― MeraError with code PASSKEY_CANCELLED when the person dismisses a prompt, it times out, or no passkey answers.
@throws ― MeraError with code PASSKEY_OPERATION_FAILED when WebAuthn is unavailable, fails for another reason, or returns an unexpected credential.
createPasskeyWithPrfOutput({
rp: PasskeyRelyingParty
Relying party identity passed to WebAuthn. id is required so the
fallback assertion can target the same relying party.
rp: {
id: string
Relying party ID: the host the passkey is scoped to.
id:
const rpId:string
rpId,
name: string
Relying party name the authenticator may show.
name: "Example" },
user: {
name: string;
displayName: string;
}
User identity passed to WebAuthn.
user: {
name: string
User name displayed or stored by the authenticator.
name: "account@example.com",
displayName: string
Human-readable display name for the authenticator UI.
The setItem() method of the Storage interface, when passed a key name and value, will add that key to the given Storage object, or update that key's value if it already exists.
Authenticator transports reported by the platform, when available.
transports,
}),
);
transports is optional and only a hint: the browser uses it to reach the authenticator directly (a platform prompt for a platform passkey, a QR flow for a phone) instead of offering every option.
Requests a passkey PRF evaluation and returns the first output.
@param ― options - Passkey PRF request inputs.
@returns ― The selected credential ID and first WebAuthn PRF output.
@remarks ―
Runs one assertion ceremony and shows one user-verification prompt.
With immediate, Chrome 148 and later (as of 2026-10) and the React Native
client show nothing when the device holds no passkey for rpId. Browsers
without immediate mode ignore the option and show their usual prompt.
Without a user gesture, or in Incognito, Chrome rejects an immediate request
with the same error even when a passkey exists.
The WebAuthn challenge is generated internally.
The default salt is sha256("mera.prf.salt.v1") and will not change across
library versions. The PRF output is a deterministic function of the
credential, rpId, and salt; a different salt yields an unrelated output.
The assertion requires user verification, and the requirement is not
configurable. User verification is the authenticator's local check; the
gesture depends on the platform (a biometric, a device PIN, or a password).
Authenticators built on CTAP's hmac-secret keep two PRFs per credential,
one for user-verified requests and one for the rest; WebAuthn exposes only
the user-verified PRF and overrides a weaker userVerification setting
when evaluating it, so a configurable setting could neither change the PRF
output nor skip the check.
@throws ― MeraError with code PRF_UNAVAILABLE when the authenticator does not return a usable 32-byte PRF output.
@throws ― MeraError with code INPUT_INVALID when an explicit prfSalt is not 32 bytes, credential.credentialId is empty or not canonical base64url, or immediate is combined with credential.
@throws ― MeraError with code CRYPTO_UNAVAILABLE when crypto.getRandomValues is unavailable.
@throws ― MeraError with code PASSKEY_CANCELLED when the person dismisses the prompt, it times out, or no passkey answers, including an immediate request that finds none.
@throws ― MeraError with code PASSKEY_OPERATION_FAILED when WebAuthn is unavailable, fails for another reason, or returns an unexpected credential.
The getItem() method of the Storage interface, when passed a key name, will return that key's value, or null if the key does not exist, in the given Storage object.
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON.
JSON.parse(text: string, reviver?:(this:any, key:string, value:any)=> any): any
Converts a JavaScript Object Notation (JSON) string into an object.
@param ― text A valid JSON string.
@param ― reviver A function that transforms the results. This function is called for each member of the object.
If a member contains nested objects, the nested objects are transformed before the parent object is.
@throws ― {SyntaxError} If text is not valid JSON.
parse(
const stored:string
stored) :
var undefined
undefined;
const {
const prfOutput:Uint8Array<ArrayBuffer>
First PRF output from WebAuthn. Always 32 bytes.
prfOutput,
const credentialId:string
Credential ID selected by the platform, as canonical unpadded base64url.
Requests a passkey PRF evaluation and returns the first output.
@param ― options - Passkey PRF request inputs.
@returns ― The selected credential ID and first WebAuthn PRF output.
@remarks ―
Runs one assertion ceremony and shows one user-verification prompt.
With immediate, Chrome 148 and later (as of 2026-10) and the React Native
client show nothing when the device holds no passkey for rpId. Browsers
without immediate mode ignore the option and show their usual prompt.
Without a user gesture, or in Incognito, Chrome rejects an immediate request
with the same error even when a passkey exists.
The WebAuthn challenge is generated internally.
The default salt is sha256("mera.prf.salt.v1") and will not change across
library versions. The PRF output is a deterministic function of the
credential, rpId, and salt; a different salt yields an unrelated output.
The assertion requires user verification, and the requirement is not
configurable. User verification is the authenticator's local check; the
gesture depends on the platform (a biometric, a device PIN, or a password).
Authenticators built on CTAP's hmac-secret keep two PRFs per credential,
one for user-verified requests and one for the rest; WebAuthn exposes only
the user-verified PRF and overrides a weaker userVerification setting
when evaluating it, so a configurable setting could neither change the PRF
output nor skip the check.
@throws ― MeraError with code PRF_UNAVAILABLE when the authenticator does not return a usable 32-byte PRF output.
@throws ― MeraError with code INPUT_INVALID when an explicit prfSalt is not 32 bytes, credential.credentialId is empty or not canonical base64url, or immediate is combined with credential.
@throws ― MeraError with code CRYPTO_UNAVAILABLE when crypto.getRandomValues is unavailable.
@throws ― MeraError with code PASSKEY_CANCELLED when the person dismisses the prompt, it times out, or no passkey answers, including an immediate request that finds none.
@throws ― MeraError with code PASSKEY_OPERATION_FAILED when WebAuthn is unavailable, fails for another reason, or returns an unexpected credential.
getPasskeyPrfOutput({
rpId: string
Relying party ID for the WebAuthn assertion.
rpId,
credential?: PasskeyCredentialMetadata |undefined
Credential metadata to restrict the assertion to one passkey. When
omitted, WebAuthn may choose any discoverable credential for the relying
party.
credential:
const known:any
known,
});
// With no stored record, the browser may have used any discoverable passkey.
const
const record:any
record =
const known:any
known?.
any
credentialId ===
const credentialId:string
Credential ID selected by the platform, as canonical unpadded base64url.
The setItem() method of the Storage interface, when passed a key name and value, will add that key to the given Storage object, or update that key's value if it already exists.
On a visit with no stored record, a single “Continue with passkey” button can sign in when the device holds a passkey and offer the other paths when it does not. immediate asks only for passkeys already on this device and rejects at once, with no prompt, when there is none:
Requests a passkey PRF evaluation and returns the first output.
@param ― options - Passkey PRF request inputs.
@returns ― The selected credential ID and first WebAuthn PRF output.
@remarks ―
Runs one assertion ceremony and shows one user-verification prompt.
With immediate, Chrome 148 and later (as of 2026-10) and the React Native
client show nothing when the device holds no passkey for rpId. Browsers
without immediate mode ignore the option and show their usual prompt.
Without a user gesture, or in Incognito, Chrome rejects an immediate request
with the same error even when a passkey exists.
The WebAuthn challenge is generated internally.
The default salt is sha256("mera.prf.salt.v1") and will not change across
library versions. The PRF output is a deterministic function of the
credential, rpId, and salt; a different salt yields an unrelated output.
The assertion requires user verification, and the requirement is not
configurable. User verification is the authenticator's local check; the
gesture depends on the platform (a biometric, a device PIN, or a password).
Authenticators built on CTAP's hmac-secret keep two PRFs per credential,
one for user-verified requests and one for the rest; WebAuthn exposes only
the user-verified PRF and overrides a weaker userVerification setting
when evaluating it, so a configurable setting could neither change the PRF
output nor skip the check.
@throws ― MeraError with code PRF_UNAVAILABLE when the authenticator does not return a usable 32-byte PRF output.
@throws ― MeraError with code INPUT_INVALID when an explicit prfSalt is not 32 bytes, credential.credentialId is empty or not canonical base64url, or immediate is combined with credential.
@throws ― MeraError with code CRYPTO_UNAVAILABLE when crypto.getRandomValues is unavailable.
@throws ― MeraError with code PASSKEY_CANCELLED when the person dismisses the prompt, it times out, or no passkey answers, including an immediate request that finds none.
@throws ― MeraError with code PASSKEY_OPERATION_FAILED when WebAuthn is unavailable, fails for another reason, or returns an unexpected credential.
A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
requested number of bytes could not be allocated an exception is raised.
Uint8Array|undefined> {
try {
const {
const prfOutput:Uint8Array<ArrayBuffer>
First PRF output from WebAuthn. Always 32 bytes.
prfOutput,
const credentialId:string
Credential ID selected by the platform, as canonical unpadded base64url.
Requests a passkey PRF evaluation and returns the first output.
@param ― options - Passkey PRF request inputs.
@returns ― The selected credential ID and first WebAuthn PRF output.
@remarks ―
Runs one assertion ceremony and shows one user-verification prompt.
With immediate, Chrome 148 and later (as of 2026-10) and the React Native
client show nothing when the device holds no passkey for rpId. Browsers
without immediate mode ignore the option and show their usual prompt.
Without a user gesture, or in Incognito, Chrome rejects an immediate request
with the same error even when a passkey exists.
The WebAuthn challenge is generated internally.
The default salt is sha256("mera.prf.salt.v1") and will not change across
library versions. The PRF output is a deterministic function of the
credential, rpId, and salt; a different salt yields an unrelated output.
The assertion requires user verification, and the requirement is not
configurable. User verification is the authenticator's local check; the
gesture depends on the platform (a biometric, a device PIN, or a password).
Authenticators built on CTAP's hmac-secret keep two PRFs per credential,
one for user-verified requests and one for the rest; WebAuthn exposes only
the user-verified PRF and overrides a weaker userVerification setting
when evaluating it, so a configurable setting could neither change the PRF
output nor skip the check.
@throws ― MeraError with code PRF_UNAVAILABLE when the authenticator does not return a usable 32-byte PRF output.
@throws ― MeraError with code INPUT_INVALID when an explicit prfSalt is not 32 bytes, credential.credentialId is empty or not canonical base64url, or immediate is combined with credential.
@throws ― MeraError with code CRYPTO_UNAVAILABLE when crypto.getRandomValues is unavailable.
@throws ― MeraError with code PASSKEY_CANCELLED when the person dismisses the prompt, it times out, or no passkey answers, including an immediate request that finds none.
@throws ― MeraError with code PASSKEY_OPERATION_FAILED when WebAuthn is unavailable, fails for another reason, or returns an unexpected credential.
getPasskeyPrfOutput({
rpId: string
Relying party ID for the WebAuthn assertion.
rpId,
immediate?: boolean |undefined
Asks only for passkeys already on this device, and rejects at once,
without a prompt, when there is none. A passkey on a phone or a
security key does not count. Cannot be combined with credential.
The setItem() method of the Storage interface, when passed a key name and value, will add that key to the given Storage object, or update that key's value if it already exists.
The trade-off: immediate skips passkeys on other devices, so a person whose passkey is on their phone gets undefined too. When prfOutput is undefined, the app offers “Create a passkey” and “Use a passkey from another device”, a sign-in without immediate. Browsers without immediate mode ignore the option and show their usual prompt.
Derives the private key of an EVM account from a PRF output.
@param ― options - PRF output and account index.
@returns ― A 32-byte secp256k1 private key.
@remarks ―
The PRF output is the entropy of a 24-word BIP-39 phrase from the English
wordlist, and the phrase's seed uses an empty passphrase. The key is the
BIP-32 key at m/44'/60'/0'/0/{accountIndex} under that seed. Wallet apps
such as MetaMask use the same path, so importing the phrase into one shows
the same accounts.
The phrase exists as a JavaScript string, which cannot be zeroed, and
@scure/bip32 leaves the intermediate keys and chain codes unzeroed.
Derives the private key of a Solana account from a PRF output.
@param ― options - PRF output and account index.
@returns ― A 32-byte Ed25519 private key (the seed).
@remarks ―
The PRF output is the entropy of a 24-word BIP-39 phrase from the English
wordlist, and the phrase's seed uses an empty passphrase. The key is the
SLIP-0010 Ed25519 key at m/44'/501'/{accountIndex}'/0' under that seed.
Wallet apps such as Phantom use the same path, so importing the phrase into
one shows the same accounts.
The phrase exists as a JavaScript string, which cannot be zeroed.
A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
requested number of bytes could not be allocated an exception is raised.
Derives the private key of an EVM account from a PRF output.
@param ― options - PRF output and account index.
@returns ― A 32-byte secp256k1 private key.
@remarks ―
The PRF output is the entropy of a 24-word BIP-39 phrase from the English
wordlist, and the phrase's seed uses an empty passphrase. The key is the
BIP-32 key at m/44'/60'/0'/0/{accountIndex} under that seed. Wallet apps
such as MetaMask use the same path, so importing the phrase into one shows
the same accounts.
The phrase exists as a JavaScript string, which cannot be zeroed, and
@scure/bip32 leaves the intermediate keys and chain codes unzeroed.
A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
requested number of bytes could not be allocated an exception is raised.
Derives the private key of a Solana account from a PRF output.
@param ― options - PRF output and account index.
@returns ― A 32-byte Ed25519 private key (the seed).
@remarks ―
The PRF output is the entropy of a 24-word BIP-39 phrase from the English
wordlist, and the phrase's seed uses an empty passphrase. The key is the
SLIP-0010 Ed25519 key at m/44'/501'/{accountIndex}'/0' under that seed.
Wallet apps such as Phantom use the same path, so importing the phrase into
one shows the same accounts.
The phrase exists as a JavaScript string, which cannot be zeroed.