Casos de uso para chaves de acesso
Este tópico descreve alguns casos de uso para chaves de acesso.
Caso de uso 1: Bootstrapping
Inicializando uma conta na web.
1.1: Autenticando o usuário
Esta seção se aplica quando a RP (terceira parte confiável) ainda não sabe quem está controlando o dispositivo cliente. Não há nenhum artefato do navegador disponível para a RP (como um cookie ou uma ID de credencial no armazenamento local), embora, por enquanto, suponhamos que o usuário tenha uma conta existente com a RP.
Para inicializar uma conta, forneça ao usuário uma página de login.
Comece solicitando ao usuário o identificador da conta; normalmente um nome de usuário ou endereço de e-mail.
Para oferecer suporte à interface do usuário de preenchimento automático para senhas, certifique-se de:
- Adicione o
username
valor andwebauthn
a todas as anotações de preenchimento automático existentes no campo de entrada do nome de usuário .
<div>
<label for="username">Username:</label>
<input name="username" id="loginform.username"
autocomplete="username webauthn">
</div>
- No carregamento da página, use uma
if
instrução para verificar se a interface do usuário de preenchimento automático (mediação condicional) está disponível e, em seguida, chamenavigator.credentials.get()
commediation: "conditional"
euserVerification: "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 fará com que aconteça o seguinte:
- Recupere as opções de autenticação do seu servidor. Retorne pelo menos um random
challenge
erpId
para ser associado a essa solicitação de autenticação. - Quando o usuário interage com seu campo de nome de usuário , o navegador e a plataforma verificam se existe uma chave de acesso (no autenticador da plataforma) que pode ser usada com a terceira parte confiável.
- Se for esse 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. Embora a aparência exata varie de uma plataforma ou fator de forma para outro:
- 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 usuário (geralmente baseada em biometria).
- Se o usuário passar com êxito na 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 varia um pouco de acordo com a plataforma), o navegador/plataforma orientará o usuário usando 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 ao 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 do autenticador de plataforma que orienta o usuário durante a verificação ou o uso do 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, nesse modo, a navigator.credentials.get()
chamada é bem-sucedida ou não, porque nunca é resolvida. Se for bem-sucedido, o resultado da chamada revelará um ID de usuário e uma declaração WebAuthn assinada, que a RP (terceira parte confiável) 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 nesta primeira página e, nas páginas subsequentes, apresentará outros desafios de login apropriados (como senhas, resposta a desafios de SMS etc.) ao usuário. Isso pode incluir etapas de recuperação de conta caso o usuário tenha esquecido sua senha ou não consiga passar nos desafios regulares de login. Depois que o usuário tiver passado por todos os desafios de login, ele será considerado autenticado e conectado.
Quando o usuário ainda não tiver uma conta com a RP (terceira parte confiável), 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 para abrir uma nova conta. Se eles abrirem uma nova conta com sucesso, eles também serão considerados autenticados e conectados.
Depois que o usuário estiver conectado, talvez seja hora de configurar uma nova chave de acesso para ele. Faça isso para qualquer um dos seguintes casos:
- O usuário inicializou sua conta no dispositivo passando por desafios de login sem chave de acesso (como usar uma senha).
- O usuário acabou de criar uma nova conta na RP (terceira parte confiável) e é considerado conectado por causa disso.
- O usuário estava usando uma chave de acesso, mas usou um dispositivo diferente do 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 precisará usar seu outro dispositivo.
1.3: Uma nota sobre a verificação do usuário
Essas diretrizes definem userVerification como preferred
, o que significa que a verificação do usuário será tentada quando possível.
Alguns dispositivos, como computadores desktop e laptops 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 a 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 ignorar 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 sempre deve ser validado em relação aos seus requisitos no servidor.
1.4: Aceitar o usuário para senhas
Primeiro, verifique se o usuário está autenticado com força suficiente usando outros métodos de login, incluindo autenticação multifator.
Em segundo lugar, verifique se a combinação de dispositivo e sistema operacional (SO) do usuário dá suporte a senhas chamando:
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
Se houver suporte para chaves de acesso, isso retornará true
. Se eles não forem suportados, ele retornará false
e você deverá anular o fluxo de inscrição da chave de acesso.
Forneça um modal/intersticial ou página opt-in ou "upsell" para o usuário oferecendo a criação de uma chave de acesso:
Dica
Para garantir que o usuário esteja dando consentimento totalmente informado, considere mostrar (ou vincular a) descrições mais longas explicando que todos os usuários que puderem desbloquear o dispositivo atual poderão acessar a conta na terceira 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 RPs (terceiras partes confiáveis) não especifique o parâmetro attestation
de transporte de atestado (portanto, o padrão é nenhum) ou, em vez disso, use 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 transferências 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 ao servidor e associe a chave pública retornada e a ID da credencial à conta de usuário autenticada anteriormente.
Caso de uso 2: Reautenticação
O uso de chaves de acesso para uma reautenticaçã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á as chaves de acesso configuradas no caso de uso anterior. A chamada à API WebAuthn é a mesma em todos os três casos, mas o tratamento da interface do usuário que você fornece é um pouco 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
Vejamos a interface do usuário primeiro pelo terceiro motivo: quando for a hora de se 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 esse ID de credencial não estiver disponível, atenda a um desafio de logon tradicional adequado para reautenticação, por exemplo:
Dica
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 possa 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:
Quando o usuário estiver pronto (no exemplo acima, quando ele clicar no botão "Ir"), chame navigator.credentials.get()
, passando todos os IDs de credencial de chave de acesso do usuário:
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
Leia as diretrizes sobre userVerification do caso de uso anterior.
Se, em vez disso, o usuário clicar em "Tentar de outra maneira", você deverá oferecer a ele outros métodos de login (senha etc.) para autenticá-lo novamente (supondo que o usuário tenha esses outros métodos de login disponíveis para ele).
2.2: Sessões expiradas e logout
Agora examinaremos o caso em que a reautenticação é disparada porque o usuário se desconectou ou a RP (terceira parte confiável) expirou a sessão do usuário. Para facilitar isso, o RP teria que manter alguma forma de estado de sessão do usuário, lembrando-o da conta que estava conectada anteriormente, mesmo quando considerasse o usuário desconectado (isso poderia ser obtido usando artefatos do navegador, como cookies ou armazenamento local).
Observação
Uma RP (terceira parte confiável) pode optar por tratar a saída como uma ação abrangente e, portanto, excluir todas as referências à identidade do usuário. Esse RP deve tratar uma entrada subsequente como um bootstrap de conta e repetir as etapas explicadas anteriormente.
Você, como RP, pode então veicular uma página de entrada como esta:
Se o usuário clicar em "Usar uma conta diferente", você deverá inserir um fluxo de bootstrap da conta, conforme explicado para o caso de uso anterior, repetindo as etapas, onde a plataforma permitirá que o usuário 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 entrada.
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 nenhuma ID de credencial estiver disponível, atenda a um desafio de login tradicional adequado para reautenticação, por exemplo:
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:
Quando o usuário estiver pronto (no exemplo acima, quando ele clicar no botão "Ir"), chame navigator.credentials.get()
, exatamente como já mostrado (ou seja, passando todos os IDs de credencial de chave de acesso do usuário).
Se, em vez disso, o usuário clicar em "Tentar de outra maneira", você deverá oferecer a ele outros métodos de login (senha etc.) para autenticá-lo novamente (supondo que o usuário tenha esses outros métodos de login disponíveis para ele).
Próximas etapas
Em seguida, consulte Ferramentas e bibliotecas para chaves de acesso.
Mais informações
- Introdução às chaves de acesso
- Passkeys.dev
- Comece sua jornada sem senha no site da FIDO Alliance
Windows developer