MasterKale / SimpleWebAuthn

WebAuthn, Simplified. A collection of TypeScript-first libraries for simpler WebAuthn integration. Supports modern browsers, Node, Deno, and more.
https://simplewebauthn.dev
MIT License
1.62k stars 137 forks source link

Allow expectedChallenge to return a promise #431

Closed jordanbtucker closed 1 year ago

jordanbtucker commented 1 year ago

Describe the issue

verifyAuthenticationResponse and verifyRegistrationResponse allow users to provide a function as the value of the expectedChallenge property of their options parameter. However, this function does not allow for returning a promise, even though both verifyAuthenticationResponse and verifyRegistrationResponse are async.

If these functions allowed expectedChallenge to return a promise, users could perform async validation of challenges (e.g. the challenge is asynchronously retrieved from the database, or the challenge included a signature that could be verified by crypto.subtle.verify in Deno). Currenlty, only sync validation is possible.

I recommend changing the signature for expectedChallenge in VerifyAuthenticationResponseOpts and VerifyRegistrationResponseOpts to be:

string | ((challenge: string) => boolean | Promise<boolean>)

Then verifyAuthenticationResponse and verifyRegistrationResponse can perform await expectedChallenge(challenge) if it's a function.

jordanbtucker commented 1 year ago

I do understand that the spec says that challenges should be randomly generated to prevent relay attacks and should "store the challenge temporarily". My use case would be to create a challenge that is a signed JWT that includes a user ID, expiration, and randomly generated nonce, effectively allowing it to be both randomly generated and temporarily stored without hitting the database.

MasterKale commented 1 year ago

@jordanbtucker This is now available in @simplewebauthn/server@8.1.0 ✌️