Retrieving stored credentials

Signing users in through the browser's password manager lets them skip the sign-in form entirely, and an account chooser gives users with multiple accounts a one-tap way to pick one. Everything below builds on navigator.credentials.get().

Auto sign-in

Auto sign-in isn't restricted to the top page — it can run on any leaf page, which matters for users who land on deeper pages via search engines. The flow is three steps:

  1. Get credential information.
  2. Authenticate the user.
  3. Update the UI or proceed to the personalized page.

Requesting credentials

Eiji Kitamura

Meggin Kearney

Call navigator.credentials.get() and request either a password or federated credential type. For auto sign-in, always pass mediation: 'silent' — this keeps the process easy to dismiss when the user has no credentials stored, has multiple credentials stored, or is signed out. Check whether the user is already signed in before requesting a credential:

if (window.PasswordCredential || window.FederatedCredential) {
  if (!user.isSignedIn()) {
    navigator.credentials.get({
      password: true,
      federated: {
        providers: ['https://accounts.google.com'],
      },
      mediation: 'silent',
    });
    // ...
  }
}

The promise resolves with either a credential object or null. Inspect the .type property — password or federated — to tell which kind you received. For federated credentials, the .provider property is a string identifying the identity provider.

Authenticating and updating the UI

Branch the authentication flow on the credential type:

    }).then(c => {
     if (c) {
       switch (c.type) {
         case 'password':
           return sendRequest(c);
           break;
         case 'federated':
           return gSignIn(c);
           break;
       }
     } else {
       return Promise.resolve();
     }

If the promise resolves without a credential object, auto sign-in couldn't happen — dismiss the process silently. On success, update the UI or forward the user to the personalized page:

    }).then(profile => {
     if (profile) {
       updateUI(profile);
     }

Signaling progress and failure

While the credential object is being retrieved, show a blue toast reading "Signing in" so the user isn't left guessing.

Blue toast showing user is signing in.

If you obtain a credential object but authentication fails, surface an error message:

        }).catch(error => {
          showError('Sign-in Failed');
        });
      }
    }

Full example

if (window.PasswordCredential || window.FederatedCredential) {
  if (!user.isSignedIn()) {
    navigator.credentials
      .get({
        password: true,
        federated: {
          providers: ['https://accounts.google.com'],
        },
        mediation: 'silent',
      })
      .then((c) => {
        if (c) {
          switch (c.type) {
            case 'password':
              return sendRequest(c);
              break;
            case 'federated':
              return gSignIn(c);
              break;
          }
        } else {
          return Promise.resolve();
        }
      })
      .then((profile) => {
        if (profile) {
          updateUI(profile);
        }
      })
      .catch((error) => {
        showError('Sign-in Failed');
      });
  }
}

Account chooser

When mediation is required, or the user has several accounts, the account chooser lets them sign in directly instead of using the ordinary form.

Google account chooser showing multiple accounts.

The steps mirror auto sign-in, with the account chooser shown as part of the credential request:

  1. Get the credential information and show the account chooser.
  2. Authenticate the user.
  3. Update the UI or proceed to a personalized page.

Showing and controlling the chooser

Trigger the chooser from a defined user action, such as a tap on the Sign-In button. Call navigator.credentials.get() with mediation: 'optional' or mediation: 'required'. With required, the account chooser always appears, which makes switching between accounts straightforward. With optional, the chooser appears after a navigator.credentials.preventSilentAccess() call — typically to keep automatic sign-in from firing after the user has signed out or unregistered.

    var signin = document.querySelector('#signin');
    signin.addEventListener('click', e => {
     if (window.PasswordCredential || window.FederatedCredential) {
       navigator.credentials.get({
         password: true,
         federated: {
           providers: [
             'https://accounts.google.com'
           ]
         },
         mediation: 'optional'
       }).then(c => {

The promise resolves with the selected credential, or with null if the user cancels the chooser or has no credentials stored.

Falling back to the sign-in form

A sign-in form fallback is needed when no credentials are stored, when the user dismisses the chooser without selecting an account, or when the API is unavailable.

    }).then(profile => {
        if (profile) {
          updateUI(profile);
        } else {
          location.href = '/signin';
        }
    }).catch(error => {
        location.href = '/signin';
    });

var signin = document.querySelector('#signin');
signin.addEventListener('click', (e) => {
  if (window.PasswordCredential || window.FederatedCredential) {
    navigator.credentials
      .get({
        password: true,
        federated: {
          providers: ['https://accounts.google.com'],
        },
        mediation: 'optional',
      })
      .then((c) => {
        if (c) {
          switch (c.type) {
            case 'password':
              return sendRequest(c);
              break;
            case 'federated':
              return gSignIn(c);
              break;
          }
        } else {
          return Promise.resolve();
        }
      })
      .then((profile) => {
        if (profile) {
          updateUI(profile);
        } else {
          location.href = '/signin';
        }
      })
      .catch((error) => {
        location.href = '/signin';
      });
  }
});

Federated login

Federated login lets users sign in with one tap and without remembering additional login details for your site. Implement it in three steps:

  1. Authenticate the user with a third-party identity.
  2. Store the identity information.
  3. Update the UI or proceed to a personalized page (identical to auto sign-in).

Authenticating through an identity provider

A tap on a federated login button should run the identity provider's own authentication flow with FederatedCredential.

Browser Support: Chrome 51, Edge 79; Firefox and Safari are not supported. (Source)

For a Google provider, use the Google Sign-In JavaScript library:

navigator.credentials
  .get({
    password: true,
    mediation: 'optional',
    federated: {
      providers: ['https://account.google.com'],
    },
  })
  .then(function (cred) {
    if (cred) {
      // Instantiate an auth object
      var auth2 = gapi.auth2.getAuthInstance();

      // Is this user already signed in?
      if (auth2.isSignedIn.get()) {
        var googleUser = auth2.currentUser.get();

        // Same user as in the credential object?
        if (googleUser.getBasicProfile().getEmail() === cred.id) {
          // Continue with the signed-in user.
          return Promise.resolve(googleUser);
        }
      }

      // Otherwise, run a new authentication flow.
      return auth2.signIn({
        login_hint: id || '',
      });
    }
  });

Google Sign-In returns an ID token as proof of authentication.

Federated logins generally sit on top of standard protocols such as OpenID Connect or OAuth, so consult the relevant provider's documentation. Common examples include Google Sign-In, Facebook Login, Twitter Sign-in and GitHub OAuth.

Storing identity information

After authentication you can persist the identity: the id from the provider plus a provider string. The name and iconURL fields are optional. Instantiate a new FederatedCredential with the user's identifier and the provider's identifier, then call navigator.credentials.store().

Construct the FederatedCredential synchronously:

// Create credential object synchronously.
var cred = new FederatedCredential({
  id: id, // id in IdP
  provider: 'https://account.google.com', // A string representing IdP
  name: name, // name in IdP
  iconURL: iconUrl, // Profile image url
});

Or asynchronously:

// Create credential object asynchronously.
var cred = await navigator.credentials.create({
  federated: {
    id: id,
    provider: 'https://accounts.google.com',
    name: name,
    iconURL: iconUrl,
  },
});

Then store it:

// Store it
navigator.credentials.store(cred).then(function () {
  // continuation
});

Signing out

On a sign-out tap, terminate the session first — how you do that is up to you — then disable auto sign-in for future visits by calling navigator.credentials.preventSilentAccess():

signoutUser();
if (navigator.credentials && navigator.credentials.preventSilentAccess) {
  navigator.credentials.preventSilentAccess();
}

Auto sign-in then stays off until the user deliberately signs in again by picking an account from the account chooser. From that point on they remain signed in until they explicitly sign out.