javascriptmacoswebauthnfido

Passkey Counter always 0 MacOS


I am learning passkey implementation for the web. I'm mainly using simplewebauthn because they're one of the FIDO conformant packages. I've been using MacOS with ICloud saved passkeys and most things seem to be working as expected however I will run into this error the second time I use a passkey: Error: Response counter value 0 was lower than expected 1

The source code is located in https://github.com/MasterKale/SimpleWebAuthn/blob/v10.0.0/packages/server/src/authentication/verifyAuthenticationResponse.ts line 224

  if (
    (counter > 0 || authenticator.counter > 0) &&
    counter <= authenticator.counter
  ) {
    // Error out when the counter in the DB is greater than or equal to the counter in the
    // dataStruct. It's related to how the authenticator maintains the number of times its been
    // used for this client. If this happens, then someone's somehow increased the counter
    // on the device without going through this site
    throw new Error(
      `Response counter value ${counter} was lower than expected ${authenticator.counter}`,
    );
  }

It looks like simplewebauthn mentions that MacOS multi-device keys might never increment counters: https://simplewebauthn.dev/docs/packages/server#3-post-registration-responsibilities

"It's also not unexpected for certain high profile authenticators, like Touch ID on macOS, to always return 0 (zero) for the signature counter. In this case there is nothing an RP can really do to detect a cloned authenticator, especially in the context of multi-device credentials."

I do have a chunk of code that has been incrementing the passkey counter each time it authenticates on MacOS, but I was wondering: Is this just how it is? Should I just not bother with incrementing the counter on my site since the MacOS ICloud saved passkeys never increment? I don't see a way to use simplewebauthn to build out a MacOS specific handling, so I could just skip the incrementing until a future date when the counter is implemented or something else updates.

The same question was asked more than a year ago for Apple app development and the suggestion passkeys.com also used simplewebauthn, but never addresses the counter. Integrating Passkeys signCount 0

I've tried not incrementing the passkey in my database and that seems to be the simplest and smoothest way to authenticate, however it leaves things vulnerable if somebody manages to copy a key.

I'm assuming for all purposes, the medium term solution is to not increment these passkeys in my database, but I'm wondering if someone has more information on why the multi-device keys don't increment and what workaround other people have been using. How dangerous is it really that someone could potentially copy one of these keys?


Solution

  • It's pretty much laid out in the WebAuthn specification. In that specification, note the use of the SHOULD keyword in regards to the signature counter; it is not an absolute requirement.

    When it comes to your relying party implementation, you should not yourself be incrementing the counter on your side. You just store the signCount value you receive from the authenticator, and upon the next authentication you compare the new signCount value against that stored value.

    Then:

    If either is non-zero, and the new signCount value is less than or equal to the stored value, a cloned authenticator may exist, or the authenticator may be malfunctioning.

    As far as the security risk assessment goes, you kind of get what you pay for. The additional convenience of using synced passkeys comes with the caveat that their level of security heavily depends on the implementing passkey provider (in most cases iCloud or Google Password Manager). This should factor into your risk assessment. If you want to further reduce risk, you could insist on the usage of properly attested hardware-backed security keys from a trusted vendor.