Algunas de las actualizaciones que se describen aquí se explican en la sesión de Google I/O, Acceso seguro y fluido: Mantén el interés de los usuarios:
Chrome 57
Chrome 57 introdujo este importante cambio en la API de Credential Management.
Las credenciales se pueden compartir desde otro subdominio
Chrome ahora puede recuperar una credencial almacenada en un subdominio diferente mediante el
API de Credential Management.
Por ejemplo, si una contraseña se almacena en login.example.com
,
una secuencia de comandos de www.example.com
puede mostrarlo como uno de los elementos de la cuenta en el diálogo del selector de cuentas.
Debes almacenar la contraseña de forma explícita con navigator.credentials.store()
,
para que, cuando un usuario elija una credencial presionando el diálogo,
la contraseña se pasa y se copia en el origen actual.
Una vez almacenada, la contraseña está disponible como credencial
con exactamente el mismo origen a partir de www.example.com
.
En la siguiente captura de pantalla, la información de credenciales almacenada en login.aliexpress.com
Es visible para m.aliexpress.com
y el usuario puede elegir entre:
Chrome 60
Chrome 60 presenta varios cambios importantes en la API de Credential Management:
Como ya no se requiere la función
fetch()
personalizada para recuperar la contraseña, dejará de estar disponible pronto.navigator.credentials.get()
ahora acepta una enummediation
en lugar de la marca booleanaunmediated
.Se cambió el nombre de
requireUserMediation()
porpreventSilentAccess()
.Nuevo método
navigator.credentials.create()
crea objetos de credenciales de forma asíncrona.
La detección de funciones requiere atención
Para ver si la API de Credential Management accede
Hay credenciales federadas disponibles. Verifica si window.PasswordCredential
o
window.FederatedCredential
está disponible.
if (window.PasswordCredential || window.FederatedCredential) {
// The Credential Management API is available
}
El objeto PasswordCredential
ahora incluye contraseña
La API de Credential Management adoptó un enfoque conservador para manejar las contraseñas.
Ocultó contraseñas de JavaScript, lo que requirió que los desarrolladores
para enviar el objeto PasswordCredential
directamente a su servidor
para la validación mediante una extensión de la API de fetch()
.
Sin embargo, este enfoque introdujo varias restricciones. Recibimos comentarios que indican que los desarrolladores no podían usar la API por los siguientes motivos:
Tuvieron que enviar la contraseña como parte de un objeto JSON.
Tuvieron que enviar el valor hash de la contraseña a su servidor.
Después de realizar un análisis de seguridad y reconocer que ocultar de JavaScript no evitó todos los vectores de ataque con la eficacia que esperábamos, decidimos hacer un cambio.
La API de Credential Management ahora incluye una contraseña sin procesar en un objeto de credencial mostrado para que puedas acceder a él como texto sin formato. Puedes usar los métodos existentes para entregar información de credenciales a tu servidor:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).then(passwordCred => {
if (passwordCred) {
let form = new FormData();
form.append('email', passwordCred.id);
form.append('password', passwordCred.password);
form.append('csrf_token', csrf_token);
return fetch('/signin', {
method: 'POST',
credentials: 'include',
body: form
});
} else {
// Fallback to sign-in form
}
}).then(res => {
if (res.status === 200) {
return res.json();
} else {
throw 'Auth failed';
}
}).then(profile => {
console.log('Auth succeeded', profile);
});
La recuperación personalizada pronto dejará de estar disponible
Para determinar si usas una función fetch()
personalizada, haz lo siguiente:
comprueba si usa un objeto PasswordCredential
o FederatedCredential
como un valor de la propiedad credentials
, por ejemplo:
fetch('/signin', {
method: 'POST',
credentials: c
})
Con una función fetch()
normal, como se muestra en el ejemplo de código anterior,
o se recomienda usar una XMLHttpRequest
.
navigator.credentials.get()
ahora acepta una mediación de enumeración
Hasta Chrome 60,
navigator.credentials.get()
aceptó una propiedad opcional de unmediated
con una marca booleana. Por ejemplo:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
unmediated: true
}).then(c => {
// Sign-in
});
Si estableces unmediated: true
, el navegador no podrá mostrar el selector de cuentas
cuando se pasa una credencial.
La marca ahora se extiende como mediación. La mediación de usuarios podría ocurrir en los siguientes casos:
El usuario debe elegir una cuenta para acceder.
Un usuario quiere acceder explícitamente después de la llamada de
navigator.credentials.requireUseMediation()
.
Elige una de las siguientes opciones para el valor mediation
:
Valor mediation |
En comparación con la marca booleana | Comportamiento | |
---|---|---|---|
silent |
Es igual a unmediated: true |
Credencial aprobada sin mostrar un selector de cuentas. | |
optional |
Es igual a unmediated: false |
Muestra un selector de cuentas si
preventSilentAccess() llamó anteriormente. |
|
required |
Una opción nueva | Mostrar siempre un selector de cuentas Es útil cuando quieres permitir que un usuario cambie de cuenta. usando el diálogo Selector de cuentas nativo. |
En este ejemplo,
la credencial se pasa sin mostrar un selector de cuentas
el equivalente de la marca anterior, unmediated: true
:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).then(c => {
// Sign-in
});
Se cambió el nombre de requireUserMediation()
por preventSilentAccess()
Para alinearse bien con la nueva propiedad mediation
que se ofrece en la llamada a get()
, haz lo siguiente:
Se cambió el nombre del método navigator.credentials.requireUserMediation()
a
navigator.credentials.preventSilentAccess()
El método con nombre nuevo evita que se pase una credencial sin mostrar el selector de cuentas (a veces llamado sin mediación del usuario). Esto es útil cuando un usuario sale de su cuenta en un sitio web o cancela su registro. de uno y no quiere volver a acceder automáticamente en la próxima visita.
signoutUser();
if (navigator.credentials) {
navigator.credentials.preventSilentAccess();
}
Crea objetos de credenciales de forma asíncrona con el nuevo método navigator.credentials.create()
.
Ahora tienes la opción de crear objetos de credenciales de forma asíncrona.
con el método nuevo, navigator.credentials.create()
.
Sigue leyendo para ver una comparación entre los enfoques síncrono y los asíncronos.
Crea un objeto PasswordCredential
Enfoque de sincronización
let c = new PasswordCredential(form);
Enfoque asíncrono (nuevo)
let c = await navigator.credentials.create({
password: form
});
o:
let c = await navigator.credentials.create({
password: {
id: id,
password: password
}
});
Crea un objeto FederatedCredential
Enfoque de sincronización
let c = new FederatedCredential({
id: 'agektmr',
name: 'Eiji Kitamura',
provider: 'https://accounts.google.com',
iconURL: 'https://*****'
});
Enfoque asíncrono (nuevo)
let c = await navigator.credentials.create({
federated: {
id: 'agektmr',
name: 'Eiji Kitamura',
provider: 'https://accounts.google.com',
iconURL: 'https://*****'
}
});
Guía de migración
¿Tienes una implementación existente de la API de Credential Management? Tenemos un documento con la guía de migración que puedes seguir para actualizarla a la nueva versión.