The Coming WebAuthn Conflict in Credential Detection

Public-key authentication through the WebAuthn spec is landing across Chrome, Firefox and Edge. One consequence: sites that use the Credential Management API (CM API) without checking for specific credential types could break when the new PublicKeyCredential objects start appearing.

The Problem

The CM API exposes a consistent interface to the browser's credential store. The core methods are:

  • navigator.credentials.get()
  • navigator.credentials.store()
  • navigator.credentials.create()
  • navigator.credentials.preventSilentAccess()

The spec originally defined only two credential types: PasswordCredential, which holds a user ID and password, and FederatedCredential, which holds a user ID along with the identity provider string. Sites use those to handle auto sign-in, save credentials after a sign-in, and keep stored credentials current when a user changes passwords.

WebAuthn is an extension of that same API. Functionally, it adds a standardized path to FIDO 2.0 authenticator devices for second-factor flows. Technically, it introduces a third credential interface: PublicKeyCredential.

The older guidance for feature-detecting support of the CM API was too coarse for a world with multiple credential types. That has to change going forward.

What Broke and Why

Previous detection guidance was not checking the credential types themselves. Early WebAuthn implementations, for instance, like the stable Firefox release planned for ~early May 2018, will cause that old approach to be fragile.

Switching the Detection Method

WebAuthn's PublicKeyCredential-specific detection is straightforward:

if (window.PublicKeyCredential) {
    // use CM API with PublicKeyCredential added in the WebAuthn spec
}

The distinction is important: generic API detection or detection of only password/federated types will not stop PublicKeyCredential instances from surfacing in navigator.credentials.* call results. Sites using those credentials without properly checking the returned type could end up sending old-style credentials where a public-key credential is expected, and vice versa.

Developers should also inspect the resulting Credential types during the mediation flow to verify that the actual credential Type is permitted by the intended operation, rather than relying on the mere existence of the parent API to establish this kind of compatibility.

For a reference implementation, see the corresponding updates in the sample code pull request provided by Google's credential-management team.