webauthn

How to include counter in WebAuth login flow


I'm building a login flow using WebAuthn.

When the passkey is already registered, from which I have initially receive a counter of `0 I then prepare the login request options as follows

 f2l = new Fido2Lib.Fido2Lib({
    rpId: 'localhost',  
    rpName: 'Bar Foo',
    rpIcon: "https://example.com/logo.png", // TODO
    attestation: 'none',
    timeout: 60000,
    challengeSize: 64,
    cryptoParams: [-7, -257],
    authenticatorAttachment: "cross-platform",
    authenticatorRequireResidentKey: false,
    authenticatorUserVerification: "required",
});

const options = await f2l.attestationOptions()
options.user = { ... }

Now when the login gets verified I do

const assertionExpectations = {
  challenge: storedChallenge,
  origin: 'http://localhost:4200', 
  factor: 'either',
  publicKey: passkey.publicKey, // Stored public key
  prevCounter: passkey.counter, // Stored counter
  userHandle: new TextEncoder().encode(user.email), // Stored user ID
} 

 const authResult = await this.f2l.assertionResult(assertionResponse, assertionExpectations);
 console.log(authResult.clientData.get('counter') // 0

Although this seems to work nicely, counter is always 0. I would expect that after a login I increase that counter. But if that is the case I also expect that I somehow include the counter in that option object for the login request. But, options.counter doesn't exist. How does this work?


Solution

  • The main goal with the signature counter is to help Relying Parties to detect copied or cloned authenticators. If there is a mismatch in the counter and stored value, then there either there has been a malfunction in the authenticator, or it has been cloned and a different one has been used.

    Passkeys are basically meant to be cloned and used across multiple devices, for example you can use the same passkey on your iPhone and your iPad. You could sync the counter across passkeys, but as said above, the real purpose is to track if the key has been used on multiple devices. So, the counter doesn't make much sense to implement in regards to passkeys and therefore, they will always return 0.

    https://www.w3.org/TR/webauthn-2/#sctn-sign-counter has some details on the ideas of the counter.