[feature] Add Type Support for PRF Extension
Describe the issue:
This issue proposes adding type support for the PRF (Pseudorandom Function) extension Currently, the library's type definitions for AuthenticationExtensionsClientInputs and AuthenticationExtensionsClientOutputs do not include properties for the prf extension. This forces developers to create custom type extensions to properly handle PRF-related data.
On the server-side, it appears that prf.eval.first (the salt value) is often being serialized as a stringified array (e.g., {"0": 43, "1": 82, ...}), which necessitates manual conversion to Uint8Array on the client.
Expected behavior
To have SimpleWebAuthn provide built-in type support for the prf extension.
Code Samples + WebAuthn Options and Responses
// server code:
> Property 'prf' does not exist on type 'AuthenticationExtensionsClientInputs'.
const options = await generateRegistrationOptions({
...restOfOptions,
extensions: {
credProps: true,
prf: {
eval: {
first: new Uint8Array(user.clientSalt),
},
},
},
});
// response to client
/**
* {
* "options": {
* "challenge": "W2pqMKD7eJMCN3Q_Y_j6Wm0FbA8zuJZAI8nUm8pwQmk",
* "rp": {
* "name": "Local Host",
* "id": "localhost"
* },
* "user": {
* "id": "tzNcKygrT66ZdOyCGung6Q",
* "name": "b7335c2b-282b-4fae-9974-ec821ae9e0e9",
* "displayName": "b7335c2b-282b-4fae-9974-ec821ae9e0e9"
* },
* "pubKeyCredParams": [
* {
* "alg": -8,
* "type": "public-key"
* },
* {
* "alg": -7,
* "type": "public-key"
* },
* {
* "alg": -257,
* "type": "public-key"
* }
* ],
* "timeout": 60000,
* "attestation": "none",
* "excludeCredentials": [],
* "authenticatorSelection": {
* "residentKey": "preferred",
* "userVerification": "preferred",
* "requireResidentKey": false,
* "authenticatorAttachment": "platform"
* },
* "extensions": {
* "credProps": true,
* "prf": {
* "eval": {
* "first": {
* "0": 43,
* "1": 82,
* "2": 74,
* "3": 195,
* "4": 24,
* "5": 235,
* "6": 224,
* "7": 14,
* "8": 244,
* "9": 153,
* "10": 32,
* "11": 192,
* "12": 0,
* "13": 9,
* "14": 54,
* "15": 236,
* "16": 5,
* "17": 158,
* "18": 4,
* "19": 79,
* "20": 33,
* "21": 27,
* "22": 214,
* "23": 93,
* "24": 57,
* "25": 45,
* "26": 235,
* "27": 173,
* "28": 113,
* "29": 9,
* "30": 15,
* "31": 202
* }
* }
* }
* },
* "hints": [
* "client-device"
* ]
* }
* }
*/
const passkeyCredential = await startRegistration({
optionsJSON: options
});
// throws an error
TypeError: Failed to execute 'create' on 'CredentialsContainer': Failed to read the 'publicKey' property from 'CredentialCreationOptions': Failed to read the 'extensions' property from 'PublicKeyCredentialCreationOptions': Failed to read the 'prf' property from 'AuthenticationExtensionsClientInputs': Failed to read the 'eval' property from 'AuthenticationExtensionsPRFInputs': Failed to read the 'first' property from 'AuthenticationExtensionsPRFValues': The provided value is not of type '(ArrayBuffer or ArrayBufferView)'
Dependencies
- OS: macOS 15.3.1
- Browser: Chrome 136.0.7103.49
- Authenticator: iCloud Keychain
SimpleWebAuthn Libraries
$ npm list --depth=0 | grep @simplewebauthn
├── @simplewebauthn/[email protected]
├── @simplewebauthn/[email protected]
# ...
Additional context
Adding support for the PRF extension will bring SimpleWebAuthn more in line with the latest WebAuthn specifications.
Hello @tarekbeb, thank you for submitting this issue. Aside from credProps (which SimpleWebAuthn has been automatically including in registration requests for quite some time) I've been of the position that extensions lie outside of "simple" use cases of passkeys - put another way, they're not necessary for the majority of passkey authentication use cases so I haven't tried to make them easier to use.
In the case of PRF, it may sound ironic given my earlier excitement for them but I actually don't want to make PRF easier to use. PRF comes with a massive footgun: if you inadvertently delete a passkey you lose all access to whatever you were encrypting with that passkey's PRF seed.
That said I can't deny that others are blazing ahead with the extension. After sitting on your issue for a couple of weeks what I think I'll do is to add a page to https://simplewebauthn.dev highlighting the availability of @simplewebauthn/server's isoBase64URL helper and @simplewebauthn/browser's bufferToBase64URLString(). Together these can be used after calling generateAuthenticationOptions(), and before and after startAuthentication() to get bytes into base64url strings and back again in between the server and browser.
Thanks for bearing with me on this :v:
Hey @MasterKale, thanks for the detailed response — I appreciate the thought you’ve put into this.
That said, I want to push back a bit. PRF isn’t just an edge case or a “non-simple” feature — it’s part of the WebAuthn spec, and I see it as a foundational tool for developers who want to build secure, user-controlled applications. Choosing not to expose it directly can unintentionally create a barrier that discourages innovation in this area.
PRF comes with a massive footgun...
I agree that using PRF requires care, but I’d argue that’s true of any cryptographic primitive. If a user deletes their passkey and loses access to encrypted data, that’s not a bug; it’s a deliberate design that gives the user complete control over their data. That kind of control is powerful and aligns with privacy-first development practices.
I believe developers can and should be trusted to build responsibly with these tools — and libraries like SimpleWebAuthn are in a great position to make these powerful features more accessible, while still including guidance and caveats. Making PRF hard to use doesn’t make developers safer, it just forces them to fork your library (like I’m doing now), and can lead to fragmentation, inconsistent implementations, or worse: insecure workarounds.
Thanks again for all your work on this library. It’s been really useful, and I hope we can find a path to support PRF that maintains your goal of simplicity while unlocking more use cases for the community.
I'm reviving this issue for myself, things have been hectic the last few weeks but are settling down. Based on the collections of reactions it's clear the demand for support is there. A docs page specifically about PRF implementation will have the added benefit of me being able to add lots of "WARNING YOU WILL SUFFER IF YOU SCREW THIS UP" messaging to raise awareness of the risks of building a feature with WebAuthn+PRF.
@V00D00-child, since I follow this work and really all of the webauthn stuff very closely and I don't understand what problem PRFs solve, can you share a specific scenario that you think everyone will run into at some point. That would make it easier for those of us who don't really understand to form an opinion on this topic.
I've got a PR up over in the docs site repo to add the guidance I mentioned above:
https://github.com/MasterKale/SimpleWebAuthn-homepage/pull/79