Partilhar via


Casos de uso para chaves de acesso

Este tópico descreve alguns casos de uso de chaves de acesso.

Caso de uso 1: Inicialização

Inicializar uma conta na Web.

1.1: Autenticando o usuário

Esta seção se aplica quando a terceira parte confiável (RP) ainda não sabe quem está controlando o dispositivo cliente. Não há nenhum artefato do navegador disponível para o RP (como um cookie ou um ID de credencial no armazenamento local), embora por enquanto suponhamos que o usuário tenha uma conta existente com o RP.

Para inicializar uma conta, forneça ao usuário uma página de login.

Comece por pedir ao utilizador o identificador da sua conta; normalmente um nome de usuário ou endereço de e-mail.

Iniciar sessão

Para suportar a interface de preenchimento automático para chaves de acesso, certifique-se de:

  1. Adicione os valores username e webauthn a todas as anotações de preenchimento automático já existentes no campo de nome de usuário.
<div>
  <label for="username">Username:</label>
  <input name="username" id="loginform.username"
         autocomplete="username webauthn">
</div>
  1. No carregamento da página, use uma instrução if para verificar se a UI de preenchimento automático (mediação condicional) está disponível e depois chame navigator.credentials.get() com mediation: "conditional" e userVerification: "preferred".
  <script>
    (async () => {
      if (
      typeof window.PublicKeyCredential !== 'undefined'
      && typeof window.PublicKeyCredential.isConditionalMediationAvailable === 'function'
      ) {
        const available = await PublicKeyCredential.isConditionalMediationAvailable();

      if (available) {
          try {
            // Retrieve authentication options for `navigator.credentials.get()`
            // from your server.
            const authOptions = await getAuthenticationOptions();
      // This call to `navigator.credentials.get()` is "set and forget."
      // The Promise will resolve only if the user successfully interacts
      // with the browser's autofill UI to select a passkey.
      const webAuthnResponse = await navigator.credentials.get({
          mediation: "conditional",
      publicKey: {
          ...authOptions,
          // See note about userVerification below.
          userVerification: "preferred",
              }
            });
      // Send the response to your server for verification, and
      // authenticate the user if the response is valid.
      await verifyAutoFillResponse(webAuthnResponse);
          } catch (err) {
          console.error('Error with conditional UI:', err);
          }
        }
      }
    })();
  </script>

O acima exposto fará com que aconteça o seguinte:

  • Recupere as opções de autenticação do seu servidor. Retorne pelo menos um valor aleatório challenge e rpId para ser associado a essa solicitação de autenticação.
  • Quando o utilizador interage com o campo de nome de utilizador, o navegador e a plataforma irão verificar se existe uma chave de acesso (no autenticador da plataforma) que pode ser usada com a entidade de confiança.
  • Se esse for o caso, a chave de acesso será apresentada ao usuário como uma opção a ser escolhida (junto com outras credenciais que podem ser preenchidas automaticamente, como nomes de usuário armazenados no gerenciador de senhas do navegador). O navegador/plataforma pode renderizar uma interface do usuário semelhante à mostrada abaixo. No entanto, a aparência exata varia de uma plataforma ou modelo para outra.

Iniciar sessão com chave de acesso

  • Se o usuário selecionar a chave de acesso, a interface do usuário da plataforma guiará o usuário por uma verificação de verificação de usuário (geralmente baseada em biometria).
  • Se o usuário passar com êxito a verificação do usuário, a navigator.credentials.get() chamada será bem-sucedida e retornará uma resposta WebAuthn.
  • Se o usuário selecionar uma credencial diferente de uma chave de acesso, o navegador/plataforma escolherá uma ação apropriada diferente (como preencher automaticamente o nome de usuário) e a navigator.credentials.get() chamada não será resolvida.
  • Se o usuário selecionar a opção "Chave de acesso de outro dispositivo" (o texto exato variará ligeiramente de acordo com a plataforma), o navegador/plataforma guiará o usuário pelo uso de uma chave de segurança FIDO2 ou o fluxo de autenticação entre dispositivos (CDA) para usar uma chave de acesso de seu smartphone ou tablet para fornecer uma resposta WebAuthn à navigator.credentials.get() chamada.
  • Envie a resposta WebAuthn para o seu servidor para verificação e verificações de segurança adicionais. Se todas as verificações forem bem-sucedidas, inicie uma sessão autenticada para esse usuário.

É por isso que isso é chamado de modo de interface do usuário condicional (ou, mais comumente, a interface do usuário de preenchimento automático) do WebAuthn — a interface do usuário autenticadora da plataforma que guia o usuário durante a verificação, ou usando seu telefone, é mostrada somente se o usuário tiver uma chave de acesso neste dispositivo (ou escolher a opção "outro dispositivo").

Como você pode ver, neste modo a navigator.credentials.get() chamada ou é bem-sucedida, ou não porque nunca resolve. Se for bem-sucedido, o resultado da chamada revelará um ID de usuário e uma asserção WebAuthn assinada, que a terceira parte confiável (RP) usará para autenticar o usuário.

Se a chamada não for bem-sucedida, você deverá executar uma autenticação de usuário herdada . Você obterá um nome de usuário a partir desta primeira página e, nas páginas subsequentes, oferecerá outros desafios de login apropriados (como senhas, resposta a desafios SMS, etc.) para o usuário. Isso pode incluir etapas de recuperação de conta caso o usuário tenha esquecido sua senha ou não seja capaz de passar pelos desafios regulares de login. Depois que o usuário passar por todos os desafios de login, ele será considerado autenticado e conectado.

Quando o usuário ainda não tem uma conta com a terceira parte confiável (RP), você geralmente dará ao usuário a opção na página de entrada para criar uma conta. Se o usuário escolher essa opção, você coletará as informações necessárias dele para abrir uma nova conta. Se abrirem uma nova conta com sucesso, também serão considerados autenticados e têm a sessão iniciada.

Depois que o usuário estiver conectado, talvez seja hora de configurar uma nova chave de acesso para ele. Faça isso em qualquer um dos seguintes casos:

  • O utilizador inicializou a sua conta no dispositivo superando desafios de autenticação que não utilizam chave de acesso (como usar uma palavra-passe).
  • O usuário acabou de criar uma nova conta na terceira parte confiável (RP) e é considerado conectado por causa disso.
  • O usuário estava usando uma chave de acesso, mas usou um dispositivo diferente daquele que está usando atualmente (selecionando "outro dispositivo" mostrado no exemplo acima). Isso pode ser confirmado inspecionando o atributo authenticatorAttachment no objeto PublicKeyCredential retornado.

1.2: Autenticação entre dispositivos

Se o usuário usou uma chave de acesso de outro dispositivo (como um telefone, tablet ou chave de segurança FIDO2), a propriedade authenticatorAttachment na resposta de autenticação (getAssertion) terá o valor cross-platform.

Nesse cenário, ofereça ao usuário a opção de criar uma chave de acesso em seu dispositivo local. Isso resultará em uma experiência de usuário mais perfeita no futuro, porque o usuário não será obrigado a usar seu outro dispositivo.

Configure uma chave de acesso neste dispositivo!

1.3: Uma nota sobre a verificação do usuário

Esta orientação define userVerification como preferred, o que significa que a tentativa de verificação do usuário será feita sempre que possível.

Alguns dispositivos, como computadores de secretária e portáteis mais antigos, podem não ter sensores biométricos. Nesses dispositivos, se userVerification estiver definido como required, o usuário poderá ser solicitado a inserir sua senha de login do sistema para cada login usando uma chave de acesso. E isso pode ser frustrante para eles.

Quando preferred é usado, alguns autenticadores de plataforma sempre exigirão uma verificação do usuário quando o dispositivo tiver sensores biométricos, mas podem dispensar a verificação do usuário em dispositivos sem eles.

O resultado da verificação do usuário (transmitido em sinalizadores de dados do autenticador) refletirá o resultado real da verificação do usuário e deve sempre ser validado em relação aos seus requisitos no servidor.

1.4: Opte pelo usuário para as chaves de acesso

Primeiro, verifique se o usuário está suficientemente autenticado usando outros métodos de login, incluindo autenticação multifator.

Em segundo lugar, certifique-se de que a combinação de dispositivo e sistema operacional (SO) do usuário suporta chaves de acesso chamando:

PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()

Se as chaves de acesso forem suportadas, então retornará true. Se eles não forem suportados, o sistema retornará false, e você deverá interromper o processo de inscrição da chave de acesso.

Servir um modal/intersticial ou página de opt-in ou "upsell" ao utilizador, oferecendo-lhes a opção de criar uma chave de acesso.

Login mais rápido e seguro com chaves de acesso!

Sugestão

Para garantir que o utilizador está a dar consentimento totalmente informado, considere mostrar (ou fornecer um link para) descrições mais detalhadas explicando que todos os utilizadores capazes de desbloquear o dispositivo presente poderão aceder à conta na parte confiável (RP).

Se o usuário consentir, ligue navigator.credentials.create() com as opções mostradas no exemplo abaixo:

navigator.credentials.create({
  publicKey: {
    rp: {
      // User-friendly name of your service.
      name: "Passkeys Developer",
      // Relying party (RP) identifier (hostname/FQDN).
      id: passkeys.contoso"
    },

    user: {
      // Persistent, unique identifier for the user account in your backend.
      id: Uint8Array.from("0525bc79-5a63-4e47-b7d1-597e25f5caba", c => c.charCodeAt(0)),
      // User-friendly identifier often displayed to the user (for example, email address).
      name: "amanda@contoso.com",
      // Human-readable display name, sometimes displayed by the client.
      displayName: "Amanda Brady"
    },
    // The challenge is a buffer of cryptographically random bytes generated on your backend,
    // and should be tightly bound to the current user session.
    challenge: Uint8Array.from("XZJscsUqtBH7ZB90t2g0EbZTZYlbSRK6lq7zlN2lJKuoYMnp7Qo2OLzD7xawL3s", c => c.charCodeAt(0)),
    pubKeyCredParams: [
      // An array of objects describing what public key types are acceptable to a server.
      {
        "type": "public-key",
        "alg": -7 // EC P256
      },
      {
        "type": "public-key",
        "alg": -257 // RSA
      }
    ],
    excludeCredentials: [
      // Array of credential IDs for existing passkeys tied to the user account.
      // This avoids creating a new passkey in an authenticator that already has 
      // a passkey tied to the user account.
      {
        // Example only.
        type: "public-key",
        id: new Uint8Array([21, 31, 56, ...]).buffer
      },
      {
        // Example only.
        type: "public-key",
        id: new Uint8Array([21, 31, 56, ...]).buffer
      }
    ],
    authenticatorSelection: {
      // Tells the authenticator to create a passkey.
      residentKey: "required",
      // Tells the client/authenticator to request user verification where possible;
      // for example, a biometric or a device PIN.
      userVerification: "preferred"
    },
    "extensions": {
      // Returns details about the passkey.
      "credProps": true
    }
  }
})

Observação

Recomendamos que a maioria das partes confiáveis (RPs) não especifique o parâmetro de transmissão de atestado attestation (deixando como padrão para nenhum) ou, em vez disso, utilize explicitamente o valor indirect. Isso garante a experiência do usuário mais simplificada (as plataformas provavelmente obterão o consentimento do usuário para outros tipos de transmissão de atestado, o que provavelmente resulta em uma fração maior de criações de credenciais malsucedidas devido ao cancelamento da criação pelos usuários).

Quando a chamada WebAuthn for resolvida, envie a resposta para o servidor e associe a chave pública retornada e o ID de credencial à conta de usuário autenticada anteriormente.

Caso de uso 2: Reautenticação

O uso de chaves de acesso para uma nova autenticação pode ser necessário por qualquer um dos seguintes motivos:

  • O usuário saiu e agora deseja entrar novamente.
  • A sessão do usuário expirou devido à inatividade e o usuário deseja entrar novamente.
  • O usuário está prestes a executar uma ação confidencial e precisa confirmar novamente o controle sobre a sessão do usuário.

Para autenticar novamente o usuário em cada uma dessas situações, você usará chaves de acesso que configurou no caso de uso anterior. A chamada de API WebAuthn é a mesma em todos os três casos, mas o tratamento da interface do usuário que você fornece é ligeiramente diferente. Como a conta específica é especificada por você, a plataforma não solicitará que o usuário selecione uma conta diferente em seu serviço.

2.1: Ações sensíveis

Vamos examinar a interface do usuário pelo terceiro motivo primeiro: quando for a hora de autenticar novamente para uma ação confidencial, verifique se você tem uma ID de credencial para pelo menos uma chave de acesso para o usuário.

Se não houver esse ID de credencial disponível, ofereça um desafio de login tradicional adequado para reautenticação, por exemplo:

Vamos ter certeza de que é você 1

Sugestão

Recomendamos que, nesta página de desafio de login, os usuários não possam alterar o identificador da conta. Além disso, o desafio de login deve ser algo que um usuário não autorizado do dispositivo não pode passar.

Se, por outro lado, você encontrar pelo menos um ID de credencial de chave de acesso para o usuário, poderá usar chaves de acesso para reautenticação:

Vamos ter certeza de que é você 2

Quando o utilizador estiver pronto (no exemplo acima, quando clicar no botão "Ir"), ligue para navigator.credentials.get(), passando todos os IDs de credenciais de passkey do utilizador:

navigator.credentials.get({
  publicKey: {
    challenge: ...,
    rpId: ...,
     allowCredentials: [{
      type: "public-key",      
      id: new UInt8Array([21, 31, 56, ...]).buffer,
    }, {
      type: "public-key",
      id: new UInt8Array([21, 31, 56, ...]).buffer,
    }, {
      ...
    }],
    // see note below
    userVerification: "preferred", 
  }
});

Observação

Certifique-se de ler as orientações sobre userVerification do caso de uso anterior.

Se, em vez disso, o utilizador clicar em "Tentar de outra forma", deve oferecer-lhe outros métodos de início de sessão (palavra-passe, etc.) para os reautenticar (assumindo que o utilizador tem esses outros métodos de início de sessão disponíveis).

2.2: Sessões expiradas e logout

Agora, examinaremos o caso em que a reautenticação é acionada porque o usuário efetuou logout ou a terceira parte confiável (RP) expirou a sessão do usuário. Para facilitar isso, o RP teria que manter algum tipo de estado de sessão do utilizador que os lembre da conta anteriormente conectada, mesmo quando considerar que o utilizador saiu. Isso pode ser conseguido através de artefactos do navegador, como cookies ou armazenamento local.

Observação

Uma terceira parte confiável (RP) pode optar por tratar a saída como uma ação abrangente e, assim, excluir todas as referências à identidade do usuário. Esse RP deve tratar um login subsequente como uma inicialização de conta e repetir as etapas explicadas anteriormente.

Você, como RP, pode então servir uma página de entrada como esta:

Bem-vindo de volta! 1

Se o utilizador clicar em "Usar uma conta diferente", deve-se iniciar um processo inicial da conta — como explicado para o caso de uso anterior — repetindo as etapas como indicado, onde a plataforma permitirá que o utilizador selecione qual conta deseja usar.

Observação

Nesse caso, você também deve dar ao usuário a capacidade de remover completamente a conta sugerida de ser listada na página de login.

Mas se o usuário clicar no botão "Entrar como", verifique se você tem pelo menos um ID de credencial de chave de acesso associado ao usuário. Se nenhum ID de credencial estiver disponível, ofereça um desafio de login tradicional adequado para reautenticação, por exemplo:

Bem-vindo de volta! 2

Se, por outro lado, você encontrar pelo menos um ID de credencial de chave de acesso para o usuário, poderá usar chaves de acesso para reautenticação:

Bem-vindo de volta! 3

Quando o utilizador estiver pronto (no exemplo acima, quando clicar no botão "Ir"), chame navigator.credentials.get(), exatamente como já mostrado (ou seja, passando todos os IDs de credenciais da chave de acesso do utilizador).

Se, em vez disso, o utilizador clicar em "Tentar de outra forma", deve oferecer-lhe outros métodos de início de sessão (palavra-passe, etc.) para os reautenticar (assumindo que o utilizador tem esses outros métodos de início de sessão disponíveis).

Próximos passos

Em seguida, consulte Ferramentas e bibliotecas para chaves de acesso.

Mais informações