Credential Management API Feature Detection Check-up

Summary

WebAuthn helps increase security by bringing public-key credential based authentication to the Web, and is soon to be supported in Chrome, Firefox and Edge (with the updated spec). It adds a new kind of Credential object, which, however, may break websites that use the Credential Management API without feature-detecting the specific credential types they're using.

If you are currently doing this for feature detection

if (navigator.credentials && navigator.credentials.preventSilentAccess) {
    // use CM API
}

Do these instead

if (window.PasswordCredential || window.FederatedCredential) {
    // Call navigator.credentials.get() to retrieve stored
    // PasswordCredentials or FederatedCredentials.
}

if (window.PasswordCredential) {
    // Get/Store PasswordCredential
}

if (window.FederatedCredential) {
    // Get/Store FederatedCredential
}

if (navigator.credentials && navigator.credentials.preventSilentAccess) {
    // Call navigator.credentials.preventSilentAccess()
}

See changes made to the sample code as an example.

Read on to learn more.

What is the Credential Management API

The Credential Management API (CM API) gives websites programmatic access to the user agent’s credential store for storing/retrieving user credentials for the calling origin.

Basic APIs are:

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

The original CM API specification defines 2 credential types:

  • PasswordCredential
  • FederatedCredential

The PasswordCredential is a credential that contains user's id and password. The FederatedCredential is a credential that contains user's id and a string that represents an identity provider.

With these 2 credentials, websites can:

  • Let the user sign-in with a previously saved password-based or federated credential as soon as they land (auto sign-in),
  • Store the password-based or federated credential the user has signed in with,
  • Keep the user's sign-in credentials up-to-date (e.g. after a password change)

What is WebAuthn

WebAuthn (Web Authentication) adds public-key credentials to the CM API. For example, it gives websites a standardized way to implement second-factor authentication using FIDO 2.0 compliant authenticator devices.

On a technical level, WebAuthn extends the CM API with the PublicKeyCredential interface.

What is the problem?

Previously we have been guiding developers to feature detect the CM API with following code:

if (navigator.credentials && navigator.credentials.preventSilentAccess) {
  // Use CM API
}

But as you can see from the descriptions above, the `navigator.credentials` is
now expanded to support public-key credentials in addition to password
credentials and federated credentials.

The problem is that user agents don't necessarily support all kinds of
credentials. If you continue feature detect using `navigator.credentials`, your
website may break when you are using a certain credential type not supported by
the browser.

**Supported credential types by browsers**
<table class="properties with-heading-tint"><tbody><tr>
<th></th>
<th>PasswordCredential / FederatedCredential</th>
<th>PublicKeyCredential</th>
</tr><tr><th>Chrome
</th><td>Available
</td><td>In development
</td></tr><tr><th>Firefox
</th><td>N/A
</td><td>Aiming to ship on 60
</td></tr><tr><th>Edge
</th><td>N/A
</td><td>Implemented with <a href="https://blogs.windows.com/msedgedev/2016/04/12/a-world-without-passwords-windows-hello-in-microsoft-edge/">older API</a>. New API (navigator.credentials) coming soon.
</td></tr></tbody></table>


## The solution
You can avoid this by modifying feature detection code as follows to explicitly
test for the credential type that you intend to use.

```js
if (window.PasswordCredential || window.FederatedCredential) {
    // Call navigator.credentials.get() to retrieve stored
    // PasswordCredentials or FederatedCredentials.
}

if (window.PasswordCredential) {
    // Get/Store PasswordCredential
}

if (window.FederatedCredential) {
    // Get/Store FederatedCredential
}

if (navigator.credentials && navigator.credentials.preventSilentAccess) {
    // Call navigator.credentials.preventSilentAccess()
}

See actual changes made to the sample code as an example.

For a reference, here's how to detect PublicKeyCredential added in WebAuthn:

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

Timeline

Earliest available implementation of WebAuthn is Firefox and is planned to be stable around early May 2018.

Finally

If you have any questions, send them over to @agektmr or agektmr@chromium.org.