jaredhanson / passport-webauthn

WebAuthn authentication strategy for Passport.
https://www.passportjs.org/packages/passport-fido2-webauthn/?utm_source=github&utm_medium=referral&utm_campaign=passport-fido2-webauthn&utm_content=about
MIT License
45 stars 13 forks source link

Challenge mismatch due to differing packages used for base64 encoding/decoding #7

Open titanism opened 10 months ago

titanism commented 10 months ago

Hi there - this project uses base64url on server-side and on client-side the demo uses base64-arraybuffer (albeit an outdated version). A new version of base64-arraybuffer is at https://github.com/niklasvh/base64-arraybuffer.

We recommend a few things:

titanism commented 10 months ago

Actually, ignore this, there's a core bug in the package https://github.com/niklasvh/base64-arraybuffer/issues/42

titanism commented 10 months ago

Perhaps instead use https://github.com/mathiasbynens/base64 everywhere (it's browser-compatible too).

titanism commented 10 months ago

Note that on the client-side, you can use this for converting from base64.decode to ArrayBuffer as required by navigator.credentials.create and navigator.credentials.get:

// <https://gist.github.com/miguelmota/5b06ae5698877322d0ca?permalink_comment_id=3611597#gistcomment-3611597>
// <https://stackoverflow.com/a/31394257>
function toArrayBuffer(buffer) {
  return buffer.buffer.slice(
    buffer.byteOffset,
    buffer.byteOffset + buffer.byteLength
  );
}
titanism commented 10 months ago

Re-opening with a little updated recommendation list (instead of original):

titanism commented 10 months ago

This is what we mean by use toArrayBuffer on client-side above:

const credential = await navigator.credentials.create({
  publicKey: {
    rp: {
      name: 'SOME NAME'
    },
    user: {
      id: toArrayBuffer(base64url.toBuffer(window.USER.id)),
      // <https://blog.millerti.me/2023/02/14/controlling-the-name-displayed-during-webauthn-registration-and-authentication/>
      name: window.USER.email,
      displayName: window.USER.email
    },
    // https://chromium.googlesource.com/chromium/src/+/master/content/browser/webauth/client_data_json.md
    challenge: toArrayBuffer(base64url.toBuffer(response.body.challenge)),
titanism commented 10 months ago

Thank you @jaredhanson for all your work here on this project and package. We're implementing it on https://forwardemail.net. Reviewed a lot of the TODO's in the codebase. Happy to help maintain the project and npm releases. We also maintain @koajs, @expressjs, @ladjs, @breejs, @cabinjs, and more. If interested, just grant npm and GitHub access to the "titanism" user, and our team at @forwardemail will help maintain (we use np for releases and changelogs).

titanism commented 10 months ago

Two other issues:

hansemannn commented 5 months ago

Noticed this as well. For us, using the native "Buffer.from" instead of the third party util solved it.