Algumas das atualizações descritas aqui são explicadas na sessão do Google I/O, Login seguro e fácil: como manter os usuários engajados:
Chrome 57
O Chrome 57 introduziu essa importante mudança ao 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 o
API Credential Management.
Por exemplo, se uma senha for armazenada em login.example.com
,
um script em www.example.com
pode mostrá-lo como um dos itens de conta na caixa de diálogo do seletor de conta.
É preciso armazenar explicitamente a senha usando navigator.credentials.store()
.
assim, 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
está visível para m.aliexpress.com
e disponível para o usuário escolher:
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, ele será descontinuado em breve.navigator.credentials.get()
agora aceita um tipo enumeradomediation
em vez da sinalização booleanaunmediated
.requireUserMediation()
renomeado comopreventSilentAccess()
.Novo método
navigator.credentials.create()
cria objetos de credenciais de forma assíncrona.
A detecção de recursos requer atenção
Para verificar se a API Credential Management para acessar dados
se as credenciais federadas estiverem disponíveis, 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 o gerenciamento de senhas.
Ele ocultava senhas do JavaScript, exigindo que os desenvolvedores
enviar o objeto PasswordCredential
diretamente ao servidor
para validação por meio de uma extensão para a API fetch()
.
Mas essa abordagem introduziu uma série de restrições. Recebemos feedback informando que os desenvolvedores não conseguiram usar a API pelos seguintes motivos:
Ele precisou enviar a senha como parte de um objeto JSON.
Ele teve que enviar o valor de hash da senha para o servidor.
Depois de realizar uma análise de segurança e reconhecer que a ocultação de senhas do JavaScript não impediu todos os vetores de ataque com a 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 ele como texto simples. Você pode usar métodos existentes para enviar informações de credenciais para 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, faça o seguinte:
verifique se ele usa um objeto PasswordCredential
ou FederatedCredential
.
como um valor da propriedade credentials
, por exemplo:
fetch('/signin', {
method: 'POST',
credentials: c
})
Usando uma função fetch()
normal, como mostrado no exemplo de código anterior,
ou usar uma XMLHttpRequest
.
navigator.credentials.get()
agora aceita uma mediação de enumeração
Até o Chrome 60,
navigator.credentials.get()
aceitou uma propriedade opcional do unmediated
com uma sinalização booleana. Exemplo:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
unmediated: true
}).then(c => {
// Sign-in
});
A definição de unmediated: true
impede que o navegador mostre o seletor de conta
ao transmitir uma credencial.
A sinalização foi 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 aprovada sem mostrar um seletor de conta. | |
optional |
Igual a unmediated: false |
Mostra um seletor de conta se
preventSilentAccess() chamado anteriormente. |
|
required |
Uma nova opção | Mostrar sempre um seletor de conta. Útil quando você quer permitir que um usuário mude de conta usando a caixa de diálogo do seletor de conta nativa. |
Neste exemplo,
a credencial é transmitida sem mostrar um seletor de conta,
o equivalente da 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 bem com a 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 mediação do usuário). Isso é útil quando um usuário sai de um site ou cancela a inscrição. e não queira ser conectado automaticamente 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 credenciais de forma assíncrona.
com o novo método, navigator.credentials.create()
.
Continue lendo para conferir uma comparação entre as abordagens de sincronização e assí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
Você já implementou a API Credential Management? Temos um documento com o guia de migração que você pode seguir para fazer upgrade para a nova versão.