Alcuni degli aggiornamenti descritti qui sono spiegati nella sessione Google I/O Accesso sicuro e semplice: mantenere gli utenti coinvolti:
Chrome 57
Chrome 57 ha introdotto questa importante modifica all'API Credential Management.
Le credenziali possono essere condivise da un sottodominio diverso
Ora Chrome può recuperare una credenziale memorizzata in un sottodominio diverso utilizzando l'API Credential Management.
Ad esempio, se una password è memorizzata in login.example.com
,
uno script su login.example.com
può mostrarla come uno degli elementi dell'account nella finestra di dialogo di scelta dell'account.www.example.com
Devi memorizzare esplicitamente la password utilizzando navigator.credentials.store()
,
in modo che quando un utente sceglie una credenziale toccando la finestra di dialogo,
la password venga passata e copiata nell'origine corrente.
Una volta memorizzata, la password è disponibile come credenziale
nella stessa origine www.example.com
e successive.
Nello screenshot seguente, le informazioni sulle credenziali archiviate in login.aliexpress.com
sono visibili a m.aliexpress.com
e possono essere scelte dall'utente:
Chrome 60
Chrome 60 introduce diverse modifiche importanti all'API Credential Management:
Poiché la funzione
fetch()
personalizzata non è più necessaria per recuperare la password, verrà ritirata a breve.navigator.credentials.get()
ora accetta un enummediation
instead of boolean flagunmediated
.requireUserMediation()
è stato rinominato inpreventSilentAccess()
.Il nuovo metodo
navigator.credentials.create()
crea oggetti credenziali in modo asincrono.
Il rilevamento delle funzionalità richiede attenzione
Per verificare se l'API Credential Management per accedere alle credenziali federate e basate su password è disponibile, controlla se è disponibile window.PasswordCredential
o
window.FederatedCredential
.
if (window.PasswordCredential || window.FederatedCredential) {
// The Credential Management API is available
}
L'oggetto PasswordCredential
ora include la password
L'API Credential Management ha adottato un approccio conservativo per la gestione delle password.
Nascondeva le password da JavaScript, richiedendo agli sviluppatori di inviare l'oggetto PasswordCredential
direttamente al loro server per la convalida tramite un'estensione dell'API fetch()
.
Tuttavia, questo approccio ha introdotto una serie di limitazioni. Abbiamo ricevuto feedback che indicano che gli sviluppatori non sono riusciti a utilizzare l'API perché:
Dovevano inviare la password all'interno di un oggetto JSON.
Dovevano inviare il valore hash della password al proprio server.
Dopo aver eseguito un'analisi di sicurezza e aver riconosciuto che la dissimulazione delle password da JavaScript non ha impedito tutti i vettori di attacco in modo efficace come speravamo, abbiamo deciso di apportare una modifica.
L'API Credential Management ora include una password non elaborata in un oggetto delle credenziali restituito, in modo da potervi accedere in testo normale. Puoi utilizzare i metodi esistenti per fornire le informazioni sulle credenziali al tuo server:
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 funzionalità di recupero personalizzato verrà ritirata a breve
Per determinare se stai utilizzando una funzione fetch()
personalizzata, controlla se utilizza un oggetto PasswordCredential
o un oggetto FederatedCredential
come valore della proprietà credentials
, ad esempio:
fetch('/signin', {
method: 'POST',
credentials: c
})
È consigliabile utilizzare una funzione fetch()
normale come mostrato nell'esempio di codice precedente o un'espressione XMLHttpRequest
.
navigator.credentials.get()
ora accetta una mediazione enum
Fino a Chrome 60,
navigator.credentials.get()
accettava una proprietà unmediated
facoltativa
con un flag booleano. Ad esempio:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
unmediated: true
}).then(c => {
// Sign-in
});
L'impostazione unmediated: true
impedisce al browser di mostrare il selettore di account
quando viene passata una credenziale.
L'indicatore ora viene esteso come mediazione. La mediazione utente può verificarsi quando:
Un utente deve scegliere un account con cui accedere.
Un utente vuole accedere esplicitamente dopo la chiamata
navigator.credentials.requireUseMediation()
.
Scegli una delle seguenti opzioni per il valore mediation
:
Valore mediation |
Rispetto al flag booleano | Comportamento | |
---|---|---|---|
silent |
È uguale a unmediated: true |
Credenziale passata senza mostrare un selettore di account. | |
optional |
È uguale a unmediated: false |
Mostra un selettore di account se
preventSilentAccess() è stato chiamato in precedenza. |
|
required |
Una nuova opzione | Mostra sempre un selettore di account. È utile quando vuoi consentire a un utente di cambiare account utilizzando la finestra di dialogo di selezione dell'account nativa. |
In questo esempio,
la credenziale viene passata senza mostrare un selettore di account,
l'equivalente del flag precedente, unmediated: true
:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).then(c => {
// Sign-in
});
requireUserMediation()
è stato rinominato preventSilentAccess()
Per allinearsi alla nuova proprietà mediation
offerta nella chiamata get()
,
il metodo navigator.credentials.requireUserMediation()
è stato rinominato
navigator.credentials.preventSilentAccess()
.
Il metodo rinominato impedisce di passare una credenziale senza mostrare il selettore di account (a volte chiamato senza mediazione dell'utente). Questa opzione è utile quando un utente si disconnette da un sito web o annulla la registrazione e non vuole eseguire nuovamente l'accesso automaticamente alla visita successiva.
signoutUser();
if (navigator.credentials) {
navigator.credentials.preventSilentAccess();
}
Crea oggetti credenziali in modo asincrono con il nuovo metodo navigator.credentials.create()
Ora hai la possibilità di creare oggetti delle credenziali in modo asincrono con il nuovo metodo navigator.credentials.create()
.
Continua a leggere per un confronto tra gli approcci sincroni e asincroni.
Creazione di un oggetto PasswordCredential
Approccio di sincronizzazione
let c = new PasswordCredential(form);
Approccio asincrono (novità)
let c = await navigator.credentials.create({
password: form
});
oppure:
let c = await navigator.credentials.create({
password: {
id: id,
password: password
}
});
Creazione di un oggetto FederatedCredential
Approccio di sincronizzazione
let c = new FederatedCredential({
id: 'agektmr',
name: 'Eiji Kitamura',
provider: 'https://accounts.google.com',
iconURL: 'https://*****'
});
Approccio asincrono (novità)
let c = await navigator.credentials.create({
federated: {
id: 'agektmr',
name: 'Eiji Kitamura',
provider: 'https://accounts.google.com',
iconURL: 'https://*****'
}
});
Guida alla migrazione
Hai già un'implementazione dell'API Credential Management? Abbiamo una guida alla migrazione che puoi seguire per eseguire l'upgrade alla nuova versione.