Credentials Management API — Terra Webmail
NOTA: "Rewrite do post escrito em: https://braziljs.org/artigos/credentials-management-api-terra-webmail/"
Este artigo tem como objetivo mostrar por que e como foi implementada a Credential Management, bem como os benefícios dessa API, usando como exemplo o login do novo Terra Webmail.
PILARES
A API tem como base três pilares:
- salvar/gerenciar os dados da credencial;
- permitir acesso com apenas um tap no seletor de contas;
- simplificar o fluxo de acesso;
LET’S GO BABY
Sabemos que hoje em dia, por mais que pareça superficialmente simples realizar a implementação de um login, logo mais a frente pode se tornar um Frankenstein ou até mesmo acabar em um grau de complexidade alto. Muitas vezes, além de gerenciar o login da nossa aplicação, temos os logins de terceiros [Facebook, Twitter, GitHub, Google].
Como temos por costume não compartilhar senhas entre aplicações por motivos de segurança, acabamos tendo um problema para a memorizar todas elas — é nessa hora que entra o trabalho da Credential Management API. Olhando por cima, temos uma lista de:
Esses são os mais comuns, uma pessoa pode ter muito mais que isso para memorizar…
BENEFÍCIOS
- facilita a escolha em caso de múltiplos usuários;
- permite uso de interface nativa para múltiplos devices;
- identifica o login que o usuário fez anteriormente na página, mesmo que o usuário não tenha auto-login no browser, permitindo a ele se logar com apenas um tap/click.
- possibilita iteração com o browser já que ele auto-preenche campos de login/senha atualmente;
- oferece auto sign in entre diferentes dispositivos;
AUTO SIGN IN
Esse comportamento nos fez dizer “wow!”
Caso você esteja logado em sua no Google Chrome e faça login em outro dispositivo na mesma página com a mesma conta, o browser identificará que foi efetuado o login e, com isso, ocorrerá o auto sign in.
PASSO 1 — EFETUANDO LOGIN E ARMAZENANDO A CREDENCIAL
Aqui, vamos ver como foi implementada essa feature no novo Terra Webmail.
Tela de login com um formulário que contém dois campos: usuário e senha;
var loginForm = document.querySelector('#signin');
loginForm.addEventListener('submit', function(e) {
e.preventDefault(); validateLoginForm().then(function(res) {
doLogin(res.user, res.pwd);
});
});
O usuário irá digitar seu username/password para efetuar o login pela primeira vez e aí começará a mágica do Credentials.
Podemos ver que, quando o evento de envio do formulário for disparado, os valores do formulário de login serão validados. Caso esteja tudo OK, vai disparar a função doLogin, que será responsável por efetuar o login efetivo e salvar a credencial usando a Credentials Management API.
Um pouco antes de entrarmos no login, vamos validar se a feature está disponível no browser atual que estamos usando.
var cmapiAvailable = window.PasswordCredential && 'credentials' in navigator;
Agora que sabemos se está ou não disponível, podemos seguir nossa implementação.
function doLogin(user, pwd) {
return authenticate(user, pwd).then(function(response) {
// var cmapiAvailable = window.PasswordCredential && 'credentials' in navigator;
if(cmapiAvailable) {
var pwdCred = new window.PasswordCredential({
id: user,
password: pwd
});
navigator.credentials.store(pwdCred);
} return response;
});
};
A partir daqui, iremos ver o que a função doLogin faz.
Ela recebe dois parâmetros, que são os responsáveis por realizar a autenticação: user — username , pwd — password.
Após nos certificarmos termos a feature disponível, usamos os parâmetros user e pwd para criar um objeto JavaScript com os atributos id e password. Logo na próxima linha, passamos esse objeto para uma nova instância de PasswordCredential.
A variável pwdCred armazenará um objeto de credencial, o qual será possível armazenar no browser.
Esse foi o primeiro passo: efetuamos o login e, logo em seguida, a credencial foi armazenada.
Pronto. Mais fácil do que se imaginava, certo?
PASSO 2 — VERIFICANDO CREDENCIAL SALVA E AUTO SIGN IN
function autoSignin() {
// var cmapiAvailable = window.PasswordCredential && 'credentials' in navigator;
if(!cmapiAvailable) {
return;
} navigator.credentials.get({
password: true,
mediation: 'optional'
}).then(function(cred) {
if(cred) {
doLogin(cred.id, cred.password);
}
});
};
O atributo password caso não seja true, não conseguirá pegar a credencial caso existente.
A função autoSignin
é disparada logo após o carregamento da página por completo. Agora, iremos ver como e quando buscaremos a credencial caso ela seja existente.
Como já vimos, iremos na primeira linha verificar a existência da API. Caso ela não exista, “matamos” o fluxo.
O mediation pode ter os seguintes valores:
- silent: com uma ou mais pessoas, caso tenha credencial salva, tentará logar de forma silenciosa. Caso preventSilentAccess() seja disparado antes, irá ignorar a ação de tentar logar de forma silenciosa e automática.
- optional: com uma pessoa, caso tenha credencial salva, tentará logar de forma silenciosa. Caso preventSilentAccess() seja disparado antes, irá ignorar a ação de tentar logar de forma automática e abrirá o seletor de contas.
- required: sempre exibirá o seletor de contas caso já tenha memorizado alguma credencial.
POR QUE ESTAMOS USANDO OPTIONAL?
Vamos entender linha por linha.
Estamos dizendo que caso já tenha sido efetuada e salva a credencial de um login, e o usuário não tenha disparado preventSilentAccess(), ele irá tentar logar de forma automática e silenciosa.
Não havendo a credencial porque o usuário disparou o preventSilentAccess(), ‘optional’ respeita a opção do usuário e abrirá o seletor de contas caso um ou mais usernames já estejam salvos.
Optamos por permitir que o usuário tenha o poder de cancelar o auto sign in. Para isso, é necessário disparar a função preventSilentAccess(), que é a responsável por comunicar a API que, na próxima visita, não deve disparar o auto sign in.
DEBUGGER — chrome://password-manager-internals/
É possível acompanhar o que está acontecendo com a API, ver quando fluxos de auto sign in e sign out ocorrem, qual formulário ele está interceptando, entre outras coisas.
DESVANTAGENS
Por enquanto, apenas o Chrome tem suporte para essa feature, tanto desktop quanto mobile.
Porém, a API w3c credential management já está em draft na W3C.Em um futuro breve teremos uma implementação cross browser.
REFERÊNCIAS
- Credential Management API Feature Detection Check-up
- Sign-in on the Web — Credential Management API and Best Practices
- Credential Managament API — elo7
- https://twitter.com/mobtec/status/986706098257264641
- https://developers.google.com/web/updates/2018/03/webauthn-credential-management
- https://developers.google.com/web/fundamentals/security/credential-management
- https://medium.com/dev-channel/sign-in-on-the-web-credential-management-api-and-best-practices-d21aed14b6fe
- https://engenharia.elo7.com.br/credential-management-api/
- https://www.youtube.com/watch?v=NJ-sphu2DqQ&t=806s
- https://www.youtube.com/watch?v=Oy5F9h5JqEU