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

Para proporcionar una experiencia del usuario sofisticada, es importante que ayudes a los usuarios a autenticarse en tu sitio web. Los usuarios autenticados pueden interactuar entre sí mediante un perfil dedicado, sincronizar datos entre dispositivos o procesar datos mientras están sin conexión. La lista continúa. Sin embargo, crear, recordar y escribir contraseñas suele resultar engorroso para los usuarios finales, especialmente en las pantallas de dispositivos móviles, lo que los lleva a reutilizar las mismas contraseñas en diferentes sitios. Esto, por supuesto, representa un riesgo de seguridad.

La versión más reciente de Chrome (51) admite la API de Credential Management. Se trata de una propuesta de seguimiento estándar en 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 simples, los desarrolladores pueden realizar acciones potentes como las siguientes:

  • Permite que los usuarios accedan con solo un toque.
  • Recuerda la cuenta federada que el usuario utilizó 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 integraron la API de Smart Lock for Passwords para Android para ofrecer una experiencia multiplataforma fluida.

Cómo integrar la API de Credential Management a 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 está ubicado solo en la página superior? ¿Están los botones de acceso en todas partes? ¿Pueden los usuarios navegar de manera significativa por tu sitio web sin acceder? ¿La federación funciona en ventanas emergentes? ¿O requiere la interacción en varias páginas?

Es casi imposible cubrir todos esos casos, pero echemos un vistazo a una app típica de una página.

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

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

  • Mostrar un selector de cuentas al acceder: Muestra una IU nativa de selector de cuentas cuando un usuario presiona "Acceder".
  • Almacenar credenciales: Cuando accedas con correcto, ofrece almacenar la información de las credenciales en el administrador de contraseñas del navegador para usarla más tarde.
  • Permitir 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 ver estas funciones implementadas en un sitio de demostración con su código de muestra.

Mostrar el Selector de cuentas al acceder

Cuando un usuario presiona el botón "Acceder" y navega a un formulario de acceso, puedes usar navigator.credentials.get() para obtener información sobre las credenciales. Chrome mostrará una IU de selector de cuentas desde la cual el usuario podrá elegir una cuenta.

Aparece una IU de selección de cuentas para que el usuario seleccione una cuenta a la que acceder.
Aparece una IU del selector de cuentas para que el usuario seleccione una cuenta a la que 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
    ...

Usa 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

Usa 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 un 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 la administración de credenciales.

Almacenar credenciales

Cuando un usuario accede a tu sitio web con un formulario, puedes usar navigator.credentials.store() para almacenar la credencial. Se le pedirá al usuario que la 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 preguntará a los usuarios si desean almacenar la credencial (o un proveedor de federación).
Chrome les preguntará a los usuarios si desean almacenar la credencial (o un proveedor de federación)

Cómo crear y almacenar una credencial de contraseña de un elemento de formulario

El siguiente código usa 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 vuelve más tarde, es posible que la sesión haya vencido. No molestes al usuario que escriba su contraseña cada vez que regrese. Permite que el usuario vuelva a acceder automáticamente.

Cuando un usuario accede automáticamente, aparece una notificación.
Cuando un usuario accede automáticamente, aparece 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 ser similar al que viste en la sección "Mostrar el selector de cuentas al acceder". La única diferencia es que configurarás unmediated: true.

Esta acción 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 de objetos de credenciales

Mediar el acceso automático

Cuando un usuario sale de su cuenta en el 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 mediante 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 de 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 por ningún medio.

¿Es posible almacenar 3 conjuntos de dígitos para un ID con la API de Credential Management? En este momento, no. Agradeceremos 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 para la administración de contraseñas en la API de Credential Management? Puedes anular navigator.credentials y conectarla a tu extensión de Chrome a las credenciales get() o store().

Recursos

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