Fazer login de usuários

Meggin Kearney
Meggin Kearney

Para fazer login de usuários, recupere as credenciais do gerenciador de senhas do navegador e use-as para fazer login automaticamente. Para usuários com várias contas, permita que eles selecionem a conta com apenas um toque usando o seletor de contas.

Login automático

O login automático pode acontecer em qualquer lugar do seu site, não apenas na página principal, mas também em outras páginas de detalhes. Isso é útil quando os usuários acessam várias páginas do seu site por um mecanismo de pesquisa.

Para ativar o login automático:

  1. Receber informações de credenciais.
  2. Autenticar o usuário.
  3. Atualize a interface ou acesse a página personalizada.

Receber informações de credenciais

Browser Support

  • Chrome: 51.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Source

Para receber informações de credenciais, invoque navigator.credentials.get(). Especifique o tipo de credenciais a serem solicitadas fornecendo um password ou federated.

Sempre use mediation: 'silent' para logins automáticos, para que você possa dispensar o processo facilmente se o usuário:

  • Não tem credenciais armazenadas.
  • Tem várias credenciais armazenadas.
  • Não fez login.

Antes de receber uma credencial, não se esqueça de verificar se o usuário já fez login:

if (window.PasswordCredential || window.FederatedCredential) {
  if (!user.isSignedIn()) {
    navigator.credentials.get({
      password: true,
      federated: {
        providers: ['https://accounts.google.com'],
      },
      mediation: 'silent',
    });
    // ...
  }
}

A promessa retornada por navigator.credentials.get() é resolvida com um objeto de credencial ou null. Para determinar se é um PasswordCredential ou um FederatedCredential, basta observar a propriedade .type do objeto, que será password ou federated.

Se .type for federated, a propriedade .provider será uma string que representa o provedor de identidade.

Autenticar usuário

Depois de receber a credencial, execute um fluxo de autenticação dependendo do tipo de credencial, password ou federated:

    }).then(c => {
     if (c) {
       switch (c.type) {
         case 'password':
           return sendRequest(c);
           break;
         case 'federated':
           return gSignIn(c);
           break;
       }
     } else {
       return Promise.resolve();
     }

Quando a promessa for resolvida, verifique se você recebeu um objeto de credencial. Se não, significa que o login automático não foi possível. Dispensar silenciosamente o processo de login automático.

Atualizar interface

Se a autenticação for bem-sucedida, atualize a IU ou encaminhe o usuário para a página personalizada:

    }).then(profile => {
     if (profile) {
       updateUI(profile);
     }

Não se esqueça de mostrar a mensagem de erro de autenticação

Para evitar confusão, os usuários precisam ver uma mensagem azul dizendo "Fazendo login" ao receber o objeto de credencial:

Notificação azul mostrando que o usuário está fazendo login.

Uma dica importante: se você conseguir um objeto de credencial, mas não conseguir autenticar o usuário, mostre uma mensagem de erro:

        }).catch(error => {
          showError('Sign-in Failed');
        });
      }
    }

Exemplo de código completo

if (window.PasswordCredential || window.FederatedCredential) {
  if (!user.isSignedIn()) {
    navigator.credentials
      .get({
        password: true,
        federated: {
          providers: ['https://accounts.google.com'],
        },
        mediation: 'silent',
      })
      .then((c) => {
        if (c) {
          switch (c.type) {
            case 'password':
              return sendRequest(c);
              break;
            case 'federated':
              return gSignIn(c);
              break;
          }
        } else {
          return Promise.resolve();
        }
      })
      .then((profile) => {
        if (profile) {
          updateUI(profile);
        }
      })
      .catch((error) => {
        showError('Sign-in Failed');
      });
  }
}

Login pelo seletor de contas

Se um usuário precisar de mediação ou tiver várias contas, use o seletor de contas para que ele faça login, ignorando o formulário de login comum, por exemplo:

Seletor de Conta do Google mostrando várias contas.

As etapas para fazer login pelo seletor de contas são as mesmas do login automático, com uma chamada extra para mostrar o seletor de contas como parte da coleta de informações de credenciais:

  1. Receba as informações de credenciais e mostre o seletor de contas.
  2. Autentique o usuário.
  3. Atualize a interface ou acesse uma página personalizada.

Receber informações de credenciais e mostrar o seletor de contas

Mostre um seletor de contas em resposta a uma ação definida do usuário, por exemplo, quando ele toca no botão "Fazer login". Chame navigator.credentials.get() e adicione mediation: 'optional' ou mediation: 'required' para mostrar o seletor de contas.

Quando mediation é required, o usuário sempre vê um seletor de conta para fazer login. Essa opção permite que os usuários com várias contas alternem facilmente entre elas. Quando mediation é optional, um seletor de conta é mostrado explicitamente ao usuário para que ele faça login após uma chamada navigator.credentials.preventSilentAccess(). Isso normalmente é feito para garantir que o login automático não aconteça depois que o usuário sair ou cancelar o registro.

Exemplo mostrando mediation: 'optional':

    var signin = document.querySelector('#signin');
    signin.addEventListener('click', e => {
     if (window.PasswordCredential || window.FederatedCredential) {
       navigator.credentials.get({
         password: true,
         federated: {
           providers: [
             'https://accounts.google.com'
           ]
         },
         mediation: 'optional'
       }).then(c => {

Depois que o usuário seleciona uma conta, a promessa é resolvida com a credencial. Se o usuário cancelar o seletor de contas ou não houver credenciais armazenadas, a promessa será resolvida com null. Nesse caso, use a experiência do formulário de login.

Não se esqueça de voltar ao formulário de login

Você deve usar um formulário de login por qualquer um destes motivos:

  • Nenhuma credencial é armazenada.
  • O usuário dispensou o seletor de contas sem selecionar uma conta.
  • A API não está disponível.
    }).then(profile => {
        if (profile) {
          updateUI(profile);
        } else {
          location.href = '/signin';
        }
    }).catch(error => {
        location.href = '/signin';
    });

Exemplo de código completo

var signin = document.querySelector('#signin');
signin.addEventListener('click', (e) => {
  if (window.PasswordCredential || window.FederatedCredential) {
    navigator.credentials
      .get({
        password: true,
        federated: {
          providers: ['https://accounts.google.com'],
        },
        mediation: 'optional',
      })
      .then((c) => {
        if (c) {
          switch (c.type) {
            case 'password':
              return sendRequest(c);
              break;
            case 'federated':
              return gSignIn(c);
              break;
          }
        } else {
          return Promise.resolve();
        }
      })
      .then((profile) => {
        if (profile) {
          updateUI(profile);
        } else {
          location.href = '/signin';
        }
      })
      .catch((error) => {
        location.href = '/signin';
      });
  }
});

Login federado

O login federado permite que os usuários façam login com um toque e sem precisar lembrar de outros detalhes de login do seu site.

Para implementar o login federado:

  1. Autenticar o usuário com uma identidade de terceiros.
  2. Armazene as informações de identidade.
  3. Atualize a interface ou acesse uma página personalizada (o mesmo que no login automático).

Autenticar usuário com identidade de terceiros

Quando um usuário tocar em um botão de login federado, execute o fluxo de autenticação do provedor de identidade específico com o FederatedCredential.

Browser Support

  • Chrome: 51.
  • Edge: 79.
  • Firefox: not supported.
  • Safari: not supported.

Source

Por exemplo, se o provedor for o Google, use a biblioteca JavaScript do Login do Google:

navigator.credentials
  .get({
    password: true,
    mediation: 'optional',
    federated: {
      providers: ['https://account.google.com'],
    },
  })
  .then(function (cred) {
    if (cred) {
      // Instantiate an auth object
      var auth2 = gapi.auth2.getAuthInstance();

      // Is this user already signed in?
      if (auth2.isSignedIn.get()) {
        var googleUser = auth2.currentUser.get();

        // Same user as in the credential object?
        if (googleUser.getBasicProfile().getEmail() === cred.id) {
          // Continue with the signed-in user.
          return Promise.resolve(googleUser);
        }
      }

      // Otherwise, run a new authentication flow.
      return auth2.signIn({
        login_hint: id || '',
      });
    }
  });

O Login do Google resulta em um token de ID como prova de autenticação.

Em geral, os logins federados são criados com base em protocolos padrão, como OpenID Connect ou OAuth. Para saber como autenticar com contas federadas, consulte os documentos dos respectivos provedores de identidade federada. Exemplos conhecidos:

Armazenar informações de identidade

Depois que a autenticação for concluída, você poderá armazenar as informações de identidade. As informações que você vai armazenar aqui são o id do provedor de identidade e uma string que representa o provedor de identidade (name e iconURL são opcionais). Saiba mais sobre essas informações na especificação do Credential Manager.

Para armazenar detalhes de contas federadas, instancie um novo objeto FederatedCredential com o identificador do usuário e do provedor. Em seguida, invoque navigator.credentials.store() para armazenar as informações de identidade.

Após a federação, instancie um FederatedCredential de forma síncrona ou assíncrona:

Exemplo de abordagem síncrona:

// Create credential object synchronously.
var cred = new FederatedCredential({
  id: id, // id in IdP
  provider: 'https://account.google.com', // A string representing IdP
  name: name, // name in IdP
  iconURL: iconUrl, // Profile image url
});

Exemplo de abordagem assíncrona:

// Create credential object asynchronously.
var cred = await navigator.credentials.create({
  federated: {
    id: id,
    provider: 'https://accounts.google.com',
    name: name,
    iconURL: iconUrl,
  },
});

Em seguida, armazene o objeto de credencial:

// Store it
navigator.credentials.store(cred).then(function () {
  // continuation
});

Sair

Desconectar os usuários quando o botão de sair for tocado. Primeiro, encerre a sessão e desative o login automático para as próximas visitas. (A forma como você encerra as sessões é totalmente sua escolha.)

Desativar o login automático para visitas futuras

Ligue para navigator.credentials.preventSilentAccess():

signoutUser();
if (navigator.credentials && navigator.credentials.preventSilentAccess) {
  navigator.credentials.preventSilentAccess();
}

Isso garante que o login automático não vai acontecer até que o usuário o ative novamente. Para retomar o login automático, o usuário pode fazer login intencionalmente escolhendo a conta que quer usar no seletor de contas. Depois disso, o usuário sempre vai estar conectado até que saia explicitamente.

Feedback