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

cross-platform authenticator usage on android 14 #534

Closed wparad closed 8 months ago

wparad commented 8 months ago

Steps to reproduce:

FWIW, it seems that https://github.com/webauthn-open-source/fido2-lib/issues/158, also has the same issue:

This happens for multiple yubikeys (and the Brave browser authenticator). All of them work through the Brave and Firefox browsers, but when using the cross-platform authenticators on mobile (browser irrelevant) all of them get invalid signatures.

Calling await fido2lib.assertionResult(res, assertionExpectations):

      const base64url = require('base64url');
      const { verifyAuthenticationResponse } = require('@simplewebauthn/server');
      const id = 'rqinmeEqIk9P4rlj5+w4UZTRDiaHcJmuy46InojSlnEWQpidux1XPpRZYXk/t7N4nisvj/US5Wdv4EBdYfX1+g==';
      const idArrayBuffer = base64url.toBuffer(id);
      const verificationResult = await verifyAuthenticationResponse({
        expectedChallenge: base64url.encode('WlhVdGQyVnpkSHhoZFhSb2NtVnpjeTVwYjN3ME1ERmlNVEU0TUdRMFltTXhNV1ZsT1RnME1HWmtZMkV4WldReE56STNPWHctWkxIOG83YTM4U0NaZ3BCeVVJTXV0ZkxzTlpmWGRRSTNUX21DUFh5WHFLZGNCYWNBZmxpdUl0UHhmaE5IYmUyTWJRUnpKQ3Y4WEpCSVdBZVpvd3lSX1F-Z29vZ2xl'),
        expectedOrigin: "https://login.authress.io",
        expectedRPID: "authress.io",
        response: {
          id: id,
          rawId: id,
          response: {
            clientDataJSON: 'eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiV2xoVmRHUXlWbnBrU0hob1pGaFNiMk50Vm5wamVUVndZak4zTUUxRVJtbE5WRVUwVFVkUk1GbHRUWGhOVjFac1QxUm5NRTFIV210Wk1rVjRXbGRSZUU1NlNUTlBXSGN0V2t4SU9HODNZVE00VTBOYVozQkNlVlZKVFhWMFpreHpUbHBtV0dSUlNUTlVYMjFEVUZoNVdIRkxaR05DWVdOQlpteHBkVWwwVUhobWFFNUlZbVV5VFdKUlVucEtRM1k0V0VwQ1NWZEJaVnB2ZDNsU1gxRi1aMjl2WjJ4bCIsIm9yaWdpbiI6Imh0dHBzOi8vbG9naW4uYXV0aHJlc3MuaW8iLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJvcmcubW96aWxsYS5maXJlZm94In0=',
            authenticatorData: 'aIcEYStClZXHYBcsiOnRIQyLrczjunPQHtagHxFwIkIFAAAB2g==',
            signature: base64url.fromBase64('MEUCIQCUHVZ4KE1L0Id292knR44w7K/ffp7juJ/SlX5627vO6gIgG+J0R7B3Ohb4G1uRfPsdIXfc+xdrLPgWFhIvqEQw0To=')
          },
          type: 'public-key'
        },
        authenticator: {
          credentialPublicKey: cose"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEReu3J7NmGpW930G7B4Au6uU+D0TA\n9x/EpArFOZEF79u0tngM7ZvZQrpPHsuRIlVv+kfY8TccmejyvJ/cBwNUoQ==\n-----END PUBLIC KEY-----\n",
          credentialID: idArrayBuffer.buffer.slice(idArrayBuffer.byteOffset, idArrayBuffer.byteLength + idArrayBuffer.byteOffset),
          counter: 1
        }
      });

I'm using a Pixel 8, is it the source of the problem, would seem really suspicious if it were, these same hardware devices (yubikeys through the pixel work fine) Is it possible there is a weird other flow is that is causing a problem?

FWIW, I took at look at the supported devices in passkeys.dev, but I couldn't make heads or tales of whether or not this is supposed to work. I can't fathom why it wouldn't work, but it is weird that it is consistently broken with three different yubikeys, also broken with the brave browser authenticator, all work through desktop, none work through mobile, and multiple libraries have the same problem.

wparad commented 8 months ago

Okay, the issue here was that in some cases android might encode things in an inconsistent way regarding the clientDataJSON object, but this had to be resolved before passing the data into the library. That means the caller has to be extra careful to not muck with the inputs into this library.