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.
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()
.
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
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.
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
});
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.
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.
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();
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.