Optimiza el flujo de acceso con la API de administración de credenciales

Para proporcionar una experiencia del usuario sofisticada, es importante ayudar a los usuarios a autenticarse en tu sitio web. Los usuarios autenticados pueden interactuar entre sí con un perfil dedicado, sincronizar datos en varios dispositivos o procesar datos sin conexión, y la lista sigue y sigue. Sin embargo, crear, recordar y escribir contraseñas suele ser engorroso para los usuarios finales, en especial en pantallas de dispositivos móviles, lo que los lleva a volver a usar las mismas contraseñas en diferentes sitios. Por supuesto, esto es un riesgo de seguridad.

La versión más reciente de Chrome (51) admite la API de Credential Management. Es una propuesta de seguimiento de estándares en el W3C que les brinda a los desarrolladores acceso programático al administrador de credenciales de un navegador y ayuda a los usuarios a acceder con mayor facilidad.

¿Qué es la API de Credential Management?

La API de Credential Management permite a los desarrolladores almacenar y recuperar credenciales de contraseña y credenciales federadas, y proporciona 3 funciones:

  • navigator.credentials.get()
  • navigator.credentials.store()
  • navigator.credentials.requireUserMediation()

Con el uso de estas APIs sencillas, los desarrolladores pueden realizar acciones poderosas como las siguientes:

  • Permite que los usuarios accedan con un solo toque.
  • Recuerda la cuenta federada que usó el usuario para acceder.
  • Permite que los usuarios vuelvan a acceder cuando venza una sesión.

En la implementación de Chrome, las credenciales se almacenarán en el administrador de contraseñas de Chrome. Si los usuarios accedieron a Chrome, pueden sincronizar sus contraseñas en todos los dispositivos. Esas contraseñas sincronizadas también se pueden compartir con apps para Android que hayan integrado la API de Smart Lock para contraseñas para Android para obtener una experiencia multiplataforma fluida.

Cómo integrar la API de Credential Management en tu sitio

La forma en que usas la API de Credential Management con tu sitio web puede variar según su arquitectura. ¿Es una app de una sola página? ¿Es una arquitectura heredada con transiciones de página? ¿El formulario de acceso solo se encuentra en la parte superior de la página? ¿Los botones de acceso están en todas partes? ¿Los usuarios pueden navegar de forma significativa por tu sitio web sin acceder? ¿La federación funciona en ventanas emergentes? ¿O requiere la interacción entre varias páginas?

Es casi imposible abarcar todos esos casos, pero veamos una app de una sola página típica.

  • La página superior es un formulario de registro.
  • Si los usuarios presionan el botón “Acceder”, navegarán a un formulario de acceso.
  • Tanto los formularios de registro como los de acceso tienen las opciones típicas de credenciales de ID o contraseña y de integración, p.ej., con el Acceso con Google y el Acceso con Facebook.

Si usas la API de Credential Management, podrás agregar las siguientes funciones al sitio, por ejemplo:

  • Mostrar un selector de cuentas cuando se accede: Muestra una IU nativa del selector de cuentas cuando un usuario presiona "Acceder".
  • Almacena las credenciales: Cuando accedas correctamente, ofrece almacenar la información de las credenciales en el administrador de contraseñas del navegador para usarlas más adelante.
  • Permite que el usuario vuelva a acceder automáticamente: Permite que el usuario vuelva a acceder si venció una sesión.
  • Mediar el acceso automático: Una vez que un usuario salga de su cuenta, inhabilita el acceso automático para la próxima visita del usuario.

Puedes experimentar estas funciones implementadas en un sitio de demostración con su código de muestra.

Mostrar el selector de cuentas cuando accedas

Entre el toque del botón "Acceder" y la navegación a un formulario de acceso, puedes usar navigator.credentials.get() para obtener información de las credenciales. Chrome mostrará una IU del selector de cuentas desde la que el usuario puede elegir una cuenta.

Aparece una IU del selector de cuentas para que el usuario seleccione una cuenta para acceder.
Aparece una IU del selector de cuentas para que el usuario seleccione una cuenta para acceder

Obtén un objeto de credencial de contraseña

Para mostrar las credenciales de contraseña como opciones de la cuenta, usa password: true.

navigator.credentials.get({
    password: true, // `true` to obtain password credentials
}).then(function(cred) {
    // continuation
    ...

Cómo usar una credencial de contraseña para acceder

Una vez que el usuario seleccione una cuenta, la función de resolución recibirá una credencial de contraseña. Puedes enviarlo al servidor con fetch():

    // continued from previous example
}).then(function(cred) {
    if (cred) {
    if (cred.type == 'password') {
        // Construct FormData object
        var form = new FormData();

        // Append CSRF Token
        var csrf_token = document.querySelector('csrf_token').value;
        form.append('csrf_token', csrf_token);

        // You can append additional credential data to `.additionalData`
        cred.additionalData = form;

        // `POST` the credential object as `credentials`.
        // id, password and the additional data will be encoded and
        // sent to the url as the HTTP body.
        fetch(url, {           // Make sure the URL is HTTPS
        method: 'POST',      // Use POST
        credentials: cred    // Add the password credential object
        }).then(function() {
        // continuation
        });
    } else if (cred.type == 'federated') {
        // continuation

Cómo usar una credencial federada para acceder

Para mostrar cuentas federadas a un usuario, agrega federated, que toma un array de proveedores de identidad, a las opciones de get().

Cuando se almacenan varias cuentas en el administrador de contraseñas.
Cuando se almacenan varias cuentas en el administrador de contraseñas
navigator.credentials.get({
    password: true, // `true` to obtain password credentials
    federated: {
    providers: [  // Specify an array of IdP strings
        'https://accounts.google.com',
        'https://www.facebook.com'
    ]
    }
}).then(function(cred) {
    // continuation
    ...

Puedes examinar la propiedad type del objeto de credencial para ver si es PasswordCredential (type == 'password') o FederatedCredential (type == 'federated'). Si la credencial es FederatedCredential, puedes llamar a la API adecuada con la información que contiene.

    });
} else if (cred.type == 'federated') {
    // `provider` contains the identity provider string
    switch (cred.provider) {
    case 'https://accounts.google.com':
        // Federated login using Google Sign-In
        var auth2 = gapi.auth2.getAuthInstance();

        // In Google Sign-In library, you can specify an account.
        // Attempt to sign in with by using `login_hint`.
        return auth2.signIn({
        login_hint: cred.id || ''
        }).then(function(profile) {
        // continuation
        });
        break;

    case 'https://www.facebook.com':
        // Federated login using Facebook Login
        // continuation
        break;

    default:
        // show form
        break;
    }
}
// if the credential is `undefined`
} else {
// show form
Diagrama de flujo de administración de credenciales.

Almacenar credenciales

Cuando un usuario accede a tu sitio web mediante un formulario, puedes usar navigator.credentials.store() para almacenar la credencial. Se le pedirá al usuario que lo almacene o no. Según el tipo de credencial, usa new PasswordCredential() o new FederatedCredential() para crear un objeto de credencial que quieras almacenar.

Chrome les pregunta a los usuarios si quieren almacenar la credencial (o un proveedor de federación).
Chrome les pregunta a los usuarios si desean almacenar la credencial (o un proveedor de federación)

Crea y almacena una credencial de contraseña a partir de un elemento de formulario

En el siguiente código, se usan atributos autocomplete para asignar automáticamente los elementos del formulario a los parámetros del objeto PasswordCredential.

HTML html <form id="form" method="post"> <input type="text" name="id" autocomplete="username" /> <input type="password" name="password" autocomplete="current-password" /> <input type="hidden" name="csrf_token" value="******" /> </form>

JavaScript

var form = document.querySelector('\#form');
var cred = new PasswordCredential(form);
// Store it
navigator.credentials.store(cred)
.then(function() {
    // continuation
});

Crea y almacena una credencial federada

// After a federation, create a FederatedCredential object using
// information you have obtained
var cred = new FederatedCredential({
    id: id,                                  // The id for the user
    name: name,                              // Optional user name
    provider: 'https://accounts.google.com',  // A string that represents the identity provider
    iconURL: iconUrl                         // Optional user avatar image url
});
// Store it
navigator.credentials.store(cred)
.then(function() {
    // continuation
});
Diagrama de flujo de acceso.

Permite que el usuario vuelva a acceder automáticamente

Cuando un usuario sale de tu sitio web y regresa más tarde, es posible que la sesión haya caducado. No molestes al usuario para que escriba su contraseña cada vez que regrese. Permite que el usuario vuelva a acceder automáticamente.

Cuando un usuario accede automáticamente, aparecerá una notificación.
Cuando un usuario accede automáticamente, aparecerá una notificación.

Obtén un objeto de credencial

navigator.credentials.get({
    password: true, // Obtain password credentials or not
    federated: {    // Obtain federation credentials or not
    providers: [  // Specify an array of IdP strings
        'https://accounts.google.com',
        'https://www.facebook.com'
    ]
    },
    unmediated: true // `unmediated: true` lets the user automatically sign in
}).then(function(cred) {
    if (cred) {
    // auto sign-in possible
    ...
    } else {
    // auto sign-in not possible
    ...
    }
});

El código debería verse similar al que viste en la sección "Mostrar selector de cuenta cuando se accede". La única diferencia es que configurarás unmediated: true.

Esto resuelve la función de inmediato y te brinda la credencial para que el usuario acceda automáticamente. Existen algunas condiciones:

  • El usuario aceptó la función de acceso automático en una cálida bienvenida.
  • El usuario ya accedió al sitio web con la API de Credential Management.
  • El usuario solo tiene una credencial almacenada para tu origen.
  • El usuario no salió de la cuenta explícitamente en la sesión anterior.

Si no se cumple alguna de estas condiciones, se rechazará la función.

Diagrama de flujo del objeto de credencial

Mediar el acceso automático

Cuando un usuario cierra sesión en tu sitio web, es tu responsabilidad asegurarte de que no vuelva a acceder automáticamente. Para garantizar esto, la API de Credential Management proporciona un mecanismo llamado mediación. Para habilitar el modo de mediación, llama a navigator.credentials.requireUserMediation(). Siempre que el estado de mediación del usuario para el origen esté activado, si usas unmediated: true con navigator.credentials.get(), esa función se resolverá con undefined.

Mediación del acceso automático

navigator.credentials.requireUserMediation();
Diagrama de flujo del acceso automático.

Preguntas frecuentes

¿Es posible que JavaScript en el sitio web recupere una contraseña sin procesar? No. Solo puedes obtener contraseñas como parte de PasswordCredential, y no se puede exponer de ninguna manera.

¿Es posible almacenar 3 conjuntos de dígitos para un ID con la API de Credential Management? En este momento, no. Valoraremos mucho tus comentarios sobre la especificación.

¿Puedo usar la API de Credential Management dentro de un iframe? La API está restringida a contextos de nivel superior. Las llamadas a .get() o .store() en un iframe se resolverán de inmediato sin efecto.

¿Puedo integrar mi extensión de Chrome de administración de contraseñas en la API de Credential Management? Puedes anular navigator.credentials y conectarlo a tu extensión de Chrome para las credenciales de get() o store().

Recursos

Para obtener más información sobre la API de Credential Management, consulta la Guía de integración.