Algumas das atualizações descritas aqui são explicadas na sessão Login seguro e simples: como manter os usuários engajados:
Chrome 57
O Chrome 57 introduziu essa mudança importante na API Credential Management.
As credenciais podem ser compartilhadas de um subdomínio diferente
Agora, o Chrome pode recuperar uma credencial armazenada em um subdomínio diferente usando a
API Credential Management.
Por exemplo, se uma senha estiver armazenada em login.example.com
,
um script em www.example.com
poderá mostrá-la como um dos itens de conta na caixa de diálogo do seletor de conta.
Você precisa armazenar a senha explicitamente usando navigator.credentials.store()
,
para que, quando um usuário escolher uma credencial tocando na caixa de diálogo,
a senha será transmitida e copiada para a origem atual.
Depois de armazenada, a senha fica disponível como uma credencial
exatamente na mesma origem www.example.com
em diante.
Na captura de tela a seguir, as informações de credenciais armazenadas em login.aliexpress.com
ficam visíveis para m.aliexpress.com
e disponíveis para o usuário escolher:
Google Chrome 60
O Chrome 60 introduz várias mudanças importantes na API Credential Management:
Como a função
fetch()
personalizada não é mais necessária para buscar a senha, ela será descontinuada em breve.navigator.credentials.get()
agora aceita um tipo enumeradomediation
em vez da flag booleanaunmediated
.requireUserMediation()
foi renomeado comopreventSilentAccess()
.O novo método
navigator.credentials.create()
cria objetos de credencial de forma assíncrona.
A detecção de recursos requer atenção
Para conferir se a API Credential Management para acesso a credenciais baseadas em senha e
federadas está disponível, verifique se window.PasswordCredential
ou
window.FederatedCredential
está disponível.
if (window.PasswordCredential || window.FederatedCredential) {
// The Credential Management API is available
}
O objeto PasswordCredential
agora inclui uma senha
A API Credential Management adotou uma abordagem conservadora para lidar com senhas.
Ele escondeu senhas do JavaScript, exigindo que os desenvolvedores
enviassem o objeto PasswordCredential
diretamente ao servidor
para validação com uma extensão para a API fetch()
.
No entanto, essa abordagem introduziu várias restrições. Recebemos feedback informando que os desenvolvedores não conseguiram usar a API pelos seguintes motivos:
Foi preciso enviar a senha como parte de um objeto JSON.
Ele precisou enviar o valor de hash da senha para o servidor.
Depois de realizar uma análise de segurança e reconhecer que ocultar senhas do JavaScript não impedia todos os vetores de ataque com a mesma eficácia que esperávamos, decidimos fazer uma mudança.
A API Credential Management agora inclui uma senha bruta em um objeto de credencial retornado para que você tenha acesso a ela como texto simples. É possível usar métodos atuais para enviar informações de credenciais ao seu 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);
});
A busca personalizada será descontinuada em breve
Para determinar se você está usando uma função fetch()
personalizada, verifique se ela usa um objeto PasswordCredential
ou FederatedCredential
como valor da propriedade credentials
, por exemplo:
fetch('/signin', {
method: 'POST',
credentials: c
})
Recomendamos usar uma função fetch()
normal, como mostrado no exemplo de código anterior,
ou um XMLHttpRequest
.
navigator.credentials.get()
agora aceita uma mediação de tipo enumerado
Até o Chrome 60,
o navigator.credentials.get()
aceitava uma propriedade unmediated
opcional
com uma sinalização booleana. Exemplo:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
unmediated: true
}).then(c => {
// Sign-in
});
Definir unmediated: true
impede que o navegador mostre o seletor de conta
ao transmitir uma credencial.
A flag agora é estendida como mediação. A mediação do usuário pode acontecer quando:
O usuário precisa escolher uma conta para fazer login.
Um usuário quer fazer login explicitamente após a chamada
navigator.credentials.requireUseMediation()
.
Escolha uma das seguintes opções para o valor mediation
:
Valor mediation |
Em comparação com a sinalização booleana | Comportamento | |
---|---|---|---|
silent |
É igual a unmediated: true |
A credencial foi transmitida sem mostrar um seletor de conta. | |
optional |
É igual a unmediated: false |
Mostra um seletor de conta se preventSilentAccess() tiver sido chamado anteriormente. |
|
required |
Uma nova opção | Sempre mostrar um seletor de conta. Útil quando você quer permitir que um usuário troque de conta usando a caixa de diálogo seletora de conta nativa. |
Neste exemplo,
a credencial é transmitida sem mostrar um seletor de conta,
o equivalente à sinalização anterior, unmediated: true
:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).then(c => {
// Sign-in
});
requireUserMediation()
foi renomeado como preventSilentAccess()
.
Para se alinhar adequadamente à nova propriedade mediation
oferecida na chamada get()
,
o método navigator.credentials.requireUserMediation()
foi renomeado como
navigator.credentials.preventSilentAccess()
.
O método renomeado impede a transmissão de uma credencial sem mostrar o seletor de conta (às vezes chamado sem a mediação do usuário). Isso é útil quando um usuário sai ou cancela a inscrição em um site e não quer fazer login novamente na próxima visita.
signoutUser();
if (navigator.credentials) {
navigator.credentials.preventSilentAccess();
}
Criar objetos de credenciais de forma assíncrona com o novo método navigator.credentials.create()
Agora você tem a opção de criar objetos de credencial de forma assíncrona
com o novo método, navigator.credentials.create()
.
Continue lendo para ver uma comparação entre as abordagens de sincronização e síncrona.
Como criar um objeto PasswordCredential
Abordagem de sincronização
let c = new PasswordCredential(form);
Abordagem assíncrona (novo)
let c = await navigator.credentials.create({
password: form
});
ou
let c = await navigator.credentials.create({
password: {
id: id,
password: password
}
});
Como criar um objeto FederatedCredential
Abordagem de sincronização
let c = new FederatedCredential({
id: 'agektmr',
name: 'Eiji Kitamura',
provider: 'https://accounts.google.com',
iconURL: 'https://*****'
});
Abordagem assíncrona (novo)
let c = await navigator.credentials.create({
federated: {
id: 'agektmr',
name: 'Eiji Kitamura',
provider: 'https://accounts.google.com',
iconURL: 'https://*****'
}
});
Guia de migração
Já tem uma implementação da API Credential Management? Temos um documento do guia de migração que você pode seguir para fazer upgrade para a nova versão.