Fazer login de usuários

Meggin Kearney
Meggin Kearney

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

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 sobre credenciais.
  2. Autentique o usuário.
  3. Atualize a interface ou acesse a página personalizada.

Receber informações de credenciais

Compatibilidade com navegadores

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

Origem

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 dispensar o processo facilmente se o usuário:

  • Não tem credenciais armazenadas.
  • Tem várias credenciais armazenadas.
  • A conta está desconectada.

Antes de receber uma credencial, confira 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 ele é um PasswordCredential ou um FederatedCredential, basta verificar a propriedade .type do objeto, que será password ou federated.

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

Autenticar o 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, isso significa que o login automático não pode acontecer. Dispensar o processo de login automático em silêncio.

Atualizar a interface

Se a autenticação for bem-sucedida, atualize a interface 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 vão receber uma mensagem azul informando "Fazendo login" no momento de receber o objeto de credencial:

Toast azul mostrando que o usuário está fazendo login.

Uma dica importante: se você conseguir acessar 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');
      });
  }
}

Fazer login pelo seletor de contas

Se um usuário solicitar mediação ou tiver diversas contas, use o seletor de contas para deixar o usuário fazer 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 conta são as mesmas do login automático, com uma chamada adicional para mostrar o seletor de conta como parte do recebimento de informações de credenciais:

  1. Receba as informações da credencial e mostre o seletor de conta.
  2. Autentique o usuário.
  3. Atualizar a interface ou acessar uma página personalizada.

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

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

Quando mediation é required, o usuário sempre recebe um seletor de conta para fazer login. Essa opção permite que usuários com várias contas alternem facilmente entre elas. Quando mediation é optional, o usuário recebe explicitamente um seletor de contas para fazer login após uma chamada navigator.credentials.preventSilentAccess(). Isso normalmente é para garantir que o login automático não aconteça depois que o usuário escolhe 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 => {

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

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

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

  • Nenhuma credencial é armazenada.
  • O usuário dispensou o seletor de conta 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. Autentique o usuário com uma identidade de terceiros.
  2. Armazenar as informações de identidade.
  3. Atualizar a interface ou acessar uma página personalizada (igual ao login automático).

Autenticar o usuário com a identidade de terceiros

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

Compatibilidade com navegadores

  • Chrome: 51.
  • Edge: 79.
  • Firefox: não é compatível.
  • Safari: não é compatível.

Origem

Por exemplo, se o provedor for Google, use a biblioteca JavaScript do Google Sign-In:

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 gera um token de ID como prova de autenticação.

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

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 de provedor que representa o provedor de identidade. name e iconURL são opcionais. Saiba mais sobre essas informações na especificação de gerenciamento de credenciais.

Para armazenar detalhes da conta federada, 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

Desconecte os usuários quando o botão de desconexão for tocado. Primeiro, encerre a sessão e desative o login automático para visitas futuras. A forma como você encerra as sessões é totalmente sua.

Desativar o login automático para visitas futuras

Chame navigator.credentials.preventSilentAccess():

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

Isso garante que o login automático só acontecerá na próxima vez que o usuário ativar esse recurso. Para reativar o login automático, o usuário pode escolher fazer login intencionalmente selecionando a conta que deseja acessar no seletor de conta. Depois disso, o usuário sempre faz login automaticamente até sair explicitamente.

Feedback