Get your free and exclusive 80-page Banking Passkey Report
passkeys e2e playwright testing webauthn virtual authenticator

Teste E2E de Passkeys com Playwright via Autenticador Virtual WebAuthn

Aprenda a configurar testes E2E para passkeys em diferentes navegadores com Playwright, Nightwatch, Selenium e Puppeteer usando o autenticador virtual WebAuthn.

Blog-Post-Author

Anders

Created: June 17, 2025

Updated: June 20, 2025


Nossa missão é tornar a Internet um lugar mais seguro, e o novo padrão de login passkeys oferece uma solução superior para alcançar isso. É por isso que queremos ajudá-lo a entender melhor as passkeys e suas características.

1. Introdução: Teste E2E de Passkeys#

As passkeys estão se tornando cada vez mais aceitas como método de autenticação, baseando-se no Web Authentication (WebAuthn) como seu padrão subjacente. Seu aumento de popularidade é bastante recente, o que torna a documentação e outros recursos relativamente escassos. Isso, juntamente com a natureza complexa da implementação de passkeys, pode tornar desafiador para os desenvolvedores encontrar informações relevantes sobre o design, a implementação e, especialmente, o teste de passkeys para suas plataformas e serviços.

Este guia visa preencher essa lacuna, focando em aspectos do autenticador virtual WebAuthn que não são abordados em detalhes em sua documentação oficial. Por exemplo, discutimos opções de configuração para o autenticador virtual que não são autoexplicativas na documentação, bem como soluções alternativas para certos casos de uso para os quais o autenticador virtual não oferece uma solução conveniente. Além disso, este guia também é útil para desenvolvedores que estão simplesmente procurando exemplos fáceis de seguir para usar o autenticador virtual em código de teste.

Nosso guia usa exemplos do Playwright para fornecer um passo a passo simples para testar eficazmente a implementação de passkeys em seu projeto. Playwright é um framework de teste de ponta a ponta (E2E) que usa o Chrome DevTools Protocol (CDP) como protocolo para automação de navegador. Se você está procurando especificamente por exemplos técnicos de teste de passkeys no Playwright, pode pular para a Seção 5. Por outro lado, se você está usando outros frameworks de teste E2E como Puppeteer ou Selenium e deseja testar passkeys nesses frameworks, as implementações do código de teste serão idênticas ou muito semelhantes aos exemplos fornecidos neste guia, dependendo do framework que você está usando. Na próxima seção, fornecemos um contexto sobre os diferentes frameworks E2E e quão relevante este guia será para eles.

2. Contexto: Automação de Navegador e Frameworks de Teste E2E#

2.1. O que é Automação de Navegador?#

Automação de navegador, como o nome sugere, é o processo de automatizar ações repetitivas do usuário no navegador para fins de extração de dados da web ou, em nosso caso, para testar aplicações web. WebDriver e Chrome DevTools Protocol (CDP) são dois dos principais protocolos de automação de navegador relevantes para este guia, pois cada um deles fornece uma implementação do autenticador virtual WebAuthn.

2.2. O que é o WebDriver?#

WebDriver é uma interface controlada remotamente que pode ser vista como um intermediário na comunicação entre o cliente e o navegador. O foco deste protocolo é fornecer uma interface neutra em termos de plataforma e linguagem que suporte todos os principais navegadores, incluindo aqueles que não são baseados em Chromium, como Firefox e Safari. Como a interface do WebDriver precisa gerenciar uma conexão com o cliente e com o navegador, essa abordagem sacrifica velocidade e estabilidade em troca de um suporte mais amplo a navegadores (ou seja, maior instabilidade). Clientes notáveis do WebDriver incluem Selenium e Nightwatch.

Retirado de jankaritech

2.3. O que é o Chrome DevTools Protocol (CDP)?#

O Chrome DevTools Protocol (CDP), por outro lado, não possui um intermediário como a interface do WebDriver entre o cliente e o navegador. Além disso, a comunicação entre o cliente e o navegador ocorre por meio de uma conexão de soquete, em contraste com a conexão HTTP mais lenta entre o cliente e a interface do WebDriver na abordagem anterior. Esses pontos tornam o CDP muito mais rápido e menos instável que o WebDriver. A desvantagem é que este protocolo é suportado apenas por navegadores baseados em Chromium, como Chrome e Edge. Playwright e Puppeteer são exemplos de clientes que usam o CDP para se comunicar com os navegadores.

Retirado de jankaritech

2.4. Puppeteer e Playwright como Frameworks de Teste E2E baseados em CDP#

Puppeteer, assim como o Playwright, é um framework E2E construído diretamente sobre o CDP. Isso significa que tanto o Puppeteer quanto o Playwright usam a mesma implementação do autenticador virtual WebAuthn e que a comunicação da API usando o autenticador virtual WebAuthn através da conexão de soquete também é idêntica.

Para demonstrar, comparamos o código de teste tanto no Playwright quanto no Puppeteer para chamar o método getCredentials, que retorna uma lista de todas as credenciais registradas no autenticador virtual até o momento. Também anexamos um ouvinte de eventos (event listener) simples para o evento credentialAdded, que é acionado quando uma credencial de passkey é registrada com sucesso. Não se intimide com os detalhes da implementação, pois eles serão explicados nas seções posteriores. Estes exemplos servem simplesmente para demonstrar como as implementações são semelhantes entre os dois frameworks.

Ben Gould Testimonial

Ben Gould

Head of Engineering

I’ve built hundreds of integrations in my time, including quite a few with identity providers and I’ve never been so impressed with a developer experience as I have been with Corbado.

10,000+ devs trust Corbado & make the Internet safer with passkeys. Got questions? We've written 150+ blog posts on passkeys.

Join Passkeys Community

Playwright:

const client = await page.context().newCDPSession(page); await client.send('WebAuthn.enable'); const authenticatorId = const result = await client.send('WebAuthn.addVirtualAuthenticator', { options }); ... // get all credentials registered in the virtual authenticator const result = await client.send('WebAuthn.getCredentials', { authenticatorId }); console.log(result.credentials); // add a listener to the credentialAdded event to output a log to the console whenever a passkey credential is registered client.on('WebAuthn.credentialAdded', () => { console.log('Credential Added!'); });

Puppeteer:

const client = await page.target().createCDPSession(); await client.send('WebAuthn.enable'); const authenticatorId = const result = await client.send('WebAuthn.addVirtualAuthenticator', { options }); ... // get all credentials registered in the virtual authenticator const result = await client.send('WebAuthn.getCredentials', { authenticatorId }); console.log(result.credentials); // add a listener to the credentialAdded event to output a log to the console whenever a passkey credential is registered client.on('WebAuthn.credentialAdded', () => { console.log('Credential Added!'); });

Embora os métodos para inicializar a sessão CDP no início dos códigos de teste sejam ligeiramente diferentes, chamar métodos e lidar com eventos na API do autenticador virtual WebAuthn do CDP é idêntico. Isso significa que, se você pretende usar o autenticador virtual WebAuthn no Puppeteer, pode seguir este guia linha por linha.

Slack Icon

Become part of our Passkeys Community for updates & support.

Join

2.5. Selenium e Nightwatch como Frameworks de Teste E2E baseados em WebDriver#

Selenium e Nightwatch são frameworks de teste E2E que dependem do WebDriver para automação de navegador. Embora a implementação do autenticador virtual WebAuthn para WebDriver seja separada de sua implementação para CDP, suas especificações de API são semelhantes. Para quase todos os métodos na API do autenticador virtual WebAuthn do CDP, você pode encontrar um método correspondente na API do autenticador virtual WebAuthn do WebDriver. No entanto, uma coisa a notar é que, embora seja possível anexar ouvintes de eventos para quando uma passkey é adicionada ou confirmada com sucesso na API do autenticador virtual WebAuthn do CDP, isso não é possível na contraparte do WebDriver.

Selenium:

const driver = await new Builder().forBrowser('chrome').build(); const options = new VirtualAuthenticatorOptions(); await driver.addVirtualAuthenticator(options); ... // get all credentials registered in the virtual authenticator const credentials = await driver.getCredentials();

É evidente que a sintaxe para configurar a instância do autenticador virtual e fazer chamadas de API é diferente da implementação CDP correspondente. No entanto, como as especificações da API dos dois autenticadores virtuais WebAuthn são muito semelhantes, seria viável seguir este guia para escrever uma implementação correspondente em um framework de teste E2E baseado em WebDriver.

2.6. Cypress como Framework de Teste E2E com Scripting Nativo#

Cypress é um framework de teste E2E que não é construído primariamente sobre WebDriver ou CDP como os frameworks mencionados acima. Ele usa JavaScript nativo para se comunicar com o navegador. No entanto, ele fornece acesso de baixo nível ao CDP, o que significa que é possível enviar comandos CDP brutos para utilizar o autenticador virtual WebAuthn do CDP.

Substack Icon

Subscribe to our Passkeys Substack for the latest news.

Subscribe

Como a sintaxe para este acesso de baixo nível é tediosa e muito diferente dos exemplos acima, não entraremos em detalhes neste guia. No entanto, mais informações sobre como chamar comandos CDP no Cypress são explicadas neste guia. Os conceitos gerais para usar o autenticador virtual WebAuthn do CDP apresentados neste guia ainda são relevantes para aqueles que buscam testar passkeys no Cypress.

3. O que Torna o Teste E2E de Passkeys com Playwright um Problema?#

Existem muitas razões pelas quais testar a implementação de passkeys é naturalmente mais desafiador do que outras ações de usuário mais simples em um ambiente web. A necessidade de lidar com interações dinâmicas do usuário envolvidas na autenticação biométrica, como leitura de impressão digital ou reconhecimento facial, adiciona uma camada de complexidade que pode não ser prática de abordar em detalhes ao escrever testes. Como a segurança é naturalmente uma grande preocupação no contexto da autenticação, também é necessário garantir que a autenticação com passkey seja integrada de forma transparente em vários navegadores e dispositivos, sem espaço para vulnerabilidades de segurança.

4. O Autenticador Virtual WebAuthn Torna o Teste E2E de Passkeys Possível#

Simplificar a complexidade de lidar com interações dinâmicas do usuário envolvidas nas operações de passkey, bem como testar sua integração em diferentes navegadores e dispositivos, torna-se mais fácil com o uso do autenticador virtual WebAuthn.

4.1. O que é o Autenticador Virtual WebAuthn?#

O autenticador virtual WebAuthn é uma representação de software do modelo de autenticador especificado no padrão WebAuthn. Ele emula o comportamento de um dispositivo autenticador físico, como uma chave de segurança de hardware (por exemplo, YubiKey) ou um scanner biométrico (por exemplo, usado no Face ID, Touch ID ou Windows Hello), mas opera inteiramente em software (portanto, nenhuma autenticação física ou leitura de biometria está envolvida).

4.2. Quais são os Benefícios do Autenticador Virtual WebAuthn?#

Existem dois benefícios principais para o autenticador virtual WebAuthn.

4.2.1. Teste Automatizado com o Autenticador Virtual WebAuthn#

Como o WebDriver e o CDP são ferramentas de automação de navegador, é evidente que o principal caso de uso da implementação do autenticador virtual WebAuthn nesses protocolos é o teste automatizado. Aproveitando esses protocolos, o autenticador virtual permite testes simples, mas abrangentes, das funcionalidades de passkey em ambientes controlados, como frameworks de teste E2E (por exemplo, Playwright, Cypress, Nightwatch).

4.2.2. Teste Manual e Demonstração com o Autenticador Virtual WebAuthn#

O autenticador virtual WebAuthn do CDP também é acessível através das Ferramentas de Desenvolvedor (DevTools) do navegador Chrome, e pode ser usado para testes manuais ou simplesmente para fins de demonstração. Com este recurso, você pode simular a entrada de passkey em um dispositivo que não suporta passkeys nativamente. Da mesma forma, também é possível simular um ambiente sem suporte a passkeys em um dispositivo que as suporta.

A captura de tela acima mostra um exemplo de uso do autenticador virtual no Chrome para testes manuais ou fins de demonstração. Você pode ver que diferentes opções de configuração para o autenticador virtual são possíveis, e a adição e exclusão de credenciais também podem ser rastreadas. Consulte este guia do Google para obter mais informações sobre como usar o autenticador virtual em seu navegador, incluindo as opções de configuração e os valores recomendados para cada uma.

4.3. Quais são as Desvantagens do Autenticador Virtual WebAuthn?#

Embora o autenticador virtual WebAuthn seja uma solução elegante para testar implementações de passkey, existem algumas desvantagens que valem a pena notar.

4.3.1. Incapacidade de Simular Funcionalidades Específicas de Hardware#

Sendo uma solução puramente baseada em software, o autenticador virtual WebAuthn não pode replicar as características de hardware e os recursos de segurança únicos dos autenticadores físicos. A distinção entre o uso de vários autenticadores de plataforma (que são integrados a um dispositivo, como um scanner biométrico em um smartphone) e vários autenticadores de plataforma cruzada (que são dispositivos externos, como chaves de segurança de hardware) não pode ser simulada usando o autenticador virtual WebAuthn. Embora a simplificação em caixa-preta das complexidades envolvidas com vários tipos de autenticadores de plataforma e de plataforma cruzada seja uma das vantagens de usar o autenticador virtual WebAuthn, se você busca simular e testar as nuances dos diferentes tipos de autenticadores, outras soluções devem ser exploradas.

4.3.2. Documentação Escassa e Problemas Técnicos não Resolvidos#

Dada a adoção relativamente recente do WebAuthn e a novidade da tecnologia de passkeys, o ecossistema em torno dos autenticadores virtuais ainda está amadurecendo. Isso resulta em uma escassez de documentação abrangente e desafios técnicos não resolvidos, particularmente no contexto da integração de autenticadores virtuais com frameworks de teste automatizado. Este guia visa abordar esse problema, fornecendo insights abrangentes sobre o teste de passkeys em um ambiente de teste automatizado, ao mesmo tempo em que se concentra em abordar os inconvenientes ainda presentes no uso dessas ferramentas e apresentar soluções alternativas para esses problemas.

5. Como Configurar o Autenticador Virtual WebAuthn no Playwright#

Após uma instalação bem-sucedida do Playwright e suas dependências, você pode começar imediatamente a escrever seu primeiro teste criando um arquivo com um nome que termine em .spec.ts ou .test.ts com o seguinte conteúdo:

import { test, expect } from "@playwright/test"; test("my first test", async ({ page }) => { await page.goto("https://passkeys.eu"); // start simulating user actions });

Para usar o autenticador virtual WebAuthn no Playwright, basta iniciar uma sessão CDP e anexar um autenticador virtual no início de um caso de teste, da seguinte forma:

test('signup with passkey', async ({ page }) => { // Initialize a CDP session for the current page const client = await page.context().newCDPSession(page); // Enable WebAuthn environment in this session await client.send('WebAuthn.enable'); // Attach a virtual authenticator with specific options const result = await client.send('WebAuthn.addVirtualAuthenticator', { options: { protocol: 'ctap2', transport: 'internal', hasResidentKey: true, hasUserVerification: true, isUserVerified: true, automaticPresenceSimulation: false, }, }); const authenticatorId = result.authenticatorId; // Further test steps to simulate user interactions and assertions ... });

Opções para configurar o autenticador virtual WebAuthn:

  • protocol: Esta opção especifica o protocolo que o autenticador virtual utiliza. Os valores possíveis são "ctap2" e "u2f"
  • transport: Esta opção especifica o tipo de autenticador que o autenticador virtual simula. Os valores possíveis são "usb", "nfc", "ble" e "internal". Se definido como "internal", ele simula um autenticador de plataforma, enquanto outros valores simulam autenticadores de plataforma cruzada.
  • hasResidentKey: Definir como true suporta Chave Residente (ou seja, credencial detectável do lado do cliente).
  • hasUserVerification: Definir como true suporta a Verificação do Usuário. É recomendado definir como true, pois permite a simulação de entrada de passkey bem-sucedida e com falha.
  • isUserVerified: Definir como true emula um cenário de autenticação bem-sucedido, enquanto false imita uma falha de autenticação, como quando um usuário cancela a entrada da passkey. Note que esta configuração só é eficaz quando hasUserVerification está definido como true.
  • automaticPresenceSimulation: Quando definido como true, a entrada da passkey ocorre automática e imediatamente após qualquer solicitação de autenticação. Por outro lado, definir como false requer a iniciação manual da simulação de autenticação com passkey no código de teste. Optar pela simulação manual (false) é recomendado por duas razões:
    • Aumentar a legibilidade do código de teste: A simulação automática pode obscurecer o entendimento do fluxo de teste, pois as tentativas de autenticação são simuladas sem gatilhos explícitos no código de teste.
    • Evitar comportamento não intencional: A simulação automática significa que a entrada da passkey será acionada mesmo que o testador não esteja ciente de que a passkey foi solicitada. Isso é especialmente um problema para a UI Condicional, que seria mais fácil para o testador ignorar.

6. Casos de Uso do Autenticador Virtual WebAuthn#

Nesta seção, exploramos o uso dos métodos e eventos do autenticador virtual WebAuthn no contexto de casos de uso comuns e mais específicos.

6.1. Como Simular uma Tentativa de Entrada de Passkey no Playwright#

Esta pode ser a tarefa mais importante e, ao mesmo tempo, confusa ao usar o autenticador virtual WebAuthn em um código de teste, pois não há um método integrado explícito para acionar uma entrada de passkey. A solução está nas opções de configuração do autenticador virtual WebAuthn, especificamente, isUserVerified e automaticPresenceSimulation. Com essas opções, podemos simular essa interação do usuário por meio de duas abordagens diferentes descritas abaixo.

6.1.1. Abordagem 1: Simulação automática com automaticPresenceSimulation definido como true#

Caso 1: Simulando uma entrada de passkey bem-sucedida

test('signup with passkey', async ({ page }) => { ... await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); await page.getByRole('button', { name: 'Login' }).click(); // successful passkey input is automatically simulated (isUserVerified=true) await expect(page.getByRole('heading', { level: 1 })).toHaveText('Welcome!'); ... });

Simular uma entrada de passkey bem-sucedida geralmente não requer linhas adicionais no código de teste. A linha final (await expect...) espera que a página mude (acionada pela entrada implícita e bem-sucedida da passkey).

Caso 2: Simulando uma entrada de passkey cancelada (que não aciona mudanças na UI)

Testar uma entrada de passkey com falha ou cancelada é mais complicado, pois pode não levar a nenhuma mudança observável na UI. Em outras palavras, esperar que a página mude como no exemplo anterior não é adequado para garantir que a entrada da passkey tenha concluído o processamento. Verificar que a página não mudou após a entrada implícita da passkey não tem sentido, pois a verificação quase certamente acontecerá antes que a entrada da passkey tenha concluído o processamento. Embora o autenticador virtual forneça uma maneira de esperar que uma entrada de passkey bem-sucedida seja processada ouvindo a emissão de eventos (como será discutido na abordagem 2), atualmente não há uma maneira integrada de detectar uma entrada de passkey com falha ou cancelada. Uma solução alternativa seria simplesmente adicionar um tempo de espera fixo (hard timeout) para aguardar a conclusão da operação da passkey antes de verificar se a UI de fato permaneceu a mesma.

test('signup with passkey', async ({ page }) => { // Simulate a set of user actions to trigger a passkey prompt ... await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); // Simulate passkey input when prompted in the test await inputPasskey(async () => { await page.waitForTimeout(300); await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); }); // Further test steps ... });

Em ambos os casos, a legibilidade do código de teste é limitada pela natureza implícita da operação da passkey. Como mencionado anteriormente, também seria fácil ignorar quando uma UI Condicional pode ser solicitada, caso em que a operação da passkey seria concluída automaticamente sem o conhecimento do testador.

6.1.2. Abordagem 2: Simulação Manual com automaticPresenceSimulation definido como false#

Acionar manualmente uma entrada de passkey, alterando o valor da opção automaticPresenceSimulation, resolve os problemas encontrados na abordagem anterior, especialmente em termos de legibilidade do código de teste.

Caso 1: Simulando uma entrada de passkey bem-sucedida

Os trechos de código a seguir simulam uma entrada de passkey bem-sucedida:

async simulateSuccessfulPasskeyInput(operationTrigger: () => Promise<void>) { // initialize event listeners to wait for a successful passkey input event const operationCompleted = new Promise<void>(resolve => { client.on('WebAuthn.credentialAdded', () => resolve()); client.on('WebAuthn.credentialAsserted', () => resolve()); }); // set isUserVerified option to true // (so that subsequent passkey operations will be successful) await client.send('WebAuthn.setUserVerified', { authenticatorId: authenticatorId, isUserVerified: true, }); // set automaticPresenceSimulation option to true // (so that the virtual authenticator will respond to the next passkey prompt) await client.send('WebAuthn.setAutomaticPresenceSimulation', { authenticatorId: authenticatorId, enabled: true, }); // perform a user action that triggers passkey prompt await operationTrigger(); // wait to receive the event that the passkey was successfully registered or verified await operationCompleted; // set automaticPresenceSimulation option back to false await client.send('WebAuthn.setAutomaticPresenceSimulation', { authenticatorId, enabled: false, }); }
test('signup with passkey', async ({ page }) => { ... // Simulate passkey input with a promise that triggers a passkey prompt as the argument await simulateSuccessfulPasskeyInput(() => page.getByRole('button', { name: 'Create account with passkeys' }).click() ); ... });

A função auxiliar (helper function) pode ser bastante intimidadora à primeira vista. Ajuda a entender que todas as complexidades técnicas de simular uma operação de passkey são abstraídas na função auxiliar. Isso significa que, quando usada dentro do código de teste, ela torna o código simples e claro, como pode ser visto no segundo trecho de código acima.

Comparada à abordagem implícita na Seção 6.1.1, esta abordagem explícita também aumenta a legibilidade do código. Isso seria especialmente útil para quando uma UI Condicional é solicitada, pois esta abordagem explícita impede a conclusão implícita e não intencional da operação de passkey sem o conhecimento do desenvolvedor.

Agora, vamos entender cada parte da função auxiliar.

Primeiro, definimos a promise operationCompleted, que aguarda pelo evento WebAuthn.credentialAdded ou pelo evento WebAuthn.credentialAsserted, que são, como os nomes sugerem, emitidos quando uma credencial de passkey é registrada ou verificada, respectivamente. Esta promise será usada mais tarde.

Em seguida, a opção isUserVerified é definida como true, para que a operação de passkey subsequente pelo autenticador virtual WebAuthn seja bem-sucedida. A automaticPresenceSimulation também é definida como true, para que o autenticador virtual WebAuthn responda à próxima solicitação de passkey da página da web.

A espera (await) da promise operationTrigger é necessária para evitar uma condição de corrida (race condition). A condição de corrida acontece quando a página da web solicita a passkey antes que automaticPresenceSimulation seja definido como true. Para evitar isso, a ação do usuário que aciona a solicitação de passkey deve ser executada depois que automaticPresenceSimulation for definido como true. No exemplo acima, o usuário clica no botão chamado Create account with passkeys para acionar a solicitação de passkey.

Após a conclusão da ação do usuário, devemos esperar que a operação de passkey bem-sucedida seja concluída. Isso é feito aguardando a promise que definimos no início da função auxiliar. A conclusão da operação de passkey bem-sucedida é marcada pela emissão do evento WebAuthn.credentialAdded ou WebAuthn.credentialAsserted. No exemplo acima, como o usuário está registrando uma passkey, o evento WebAuthn.credentialAdded seria emitido.

Finalmente, a opção automaticPresenceSimulation é definida de volta para false, para evitar que operações de passkey não intencionais ocorram mais tarde no código de teste.

Caso 2: Simulando uma entrada de passkey cancelada

Para uma entrada de passkey cancelada, devemos fazer uma pequena modificação na implementação do caso anterior. No caso de uma entrada de passkey bem-sucedida, existem eventos, nomeadamente WebAuthn.credentialAdded e WebAuthn.credentialAsserted, que são emitidos após a conclusão da operação. No entanto, o autenticador virtual WebAuthn não fornece nenhum evento para uma entrada de passkey cancelada ou com falha. Portanto, devemos usar uma maneira alternativa para verificar a conclusão de uma operação de passkey cancelada ou com falha.

Os trechos de código a seguir simulam uma entrada de passkey com falha:

async simulateFailedPasskeyInput(operationTrigger: () => Promise<void>, postOperationCheck: () => Promise<void>) { // set isUserVerified option to false // (so that subsequent passkey operations will fail) await client.send('WebAuthn.setUserVerified', { authenticatorId: authenticatorId, isUserVerified: false, }); // set automaticPresenceSimulation option to true // (so that the virtual authenticator will respond to the next passkey prompt) await client.send('WebAuthn.setAutomaticPresenceSimulation', { authenticatorId: authenticatorId, enabled: true, }); // perform a user action that triggers passkey prompt await operationTrigger(); // wait for an expected UI change that indicates the passkey operation has completed await postOperationCheck(); // set automaticPresenceSimulation option back to false await client.send('WebAuthn.setAutomaticPresenceSimulation', { authenticatorId, enabled: false, }); }
test('signup with passkey', async ({ page }) => { // Simulate a set of user actions to trigger a passkey prompt ... await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); // Simulate passkey input when prompted in the test await inputPasskey(async () => { await page.waitForTimeout(300); await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); }); // Further test steps ... });

Na função auxiliar, os ouvintes de eventos são substituídos por um parâmetro de promise postOperationCheck, que aguarda a ocorrência de uma mudança esperada na UI antes que automaticPresenceSimulation possa ser definido de volta para false.

No código de teste, a única diferença é que a função auxiliar deve ser chamada com uma promise adicional que verifica a mudança pretendida na UI. No exemplo acima, verificamos se a aplicação web navegou com sucesso para uma página em que o cabeçalho tem o texto Something went wrong....

Como foi discutido na Seção 6.1.1, cancelar uma entrada de passkey pode não levar a nenhuma mudança observável na UI. Assim como no exemplo fornecido naquela seção, devemos adicionar uma espera fixa (hard wait) antes de verificar se a UI de fato permaneceu a mesma em tais casos:

test('signup with passkey', async ({ page }) => { ... await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); // Simulate passkey input with a promise that triggers a passkey prompt as the argument await simulateFailedPasskeyInput( () => page.getByRole('button', { name: 'Create account with passkeys' }).click(), async () => { await page.waitForTimeout(300); await expect(page.getByRole('heading', { level: 1 })).toHaveText('Please log in'); } ); ... });

6.2. Como Testar a Criação de Passkey#

A conveniência de usar um autenticador virtual WebAuthn é aprimorada por sua capacidade de se comportar como um autenticador real no caso de criação de passkey ou exclusão pela aplicação web. Um teste simplesmente precisa executar ações do usuário para simular a criação ou exclusão de uma passkey na aplicação web, e o autenticador virtual WebAuthn modifica automaticamente suas informações de credencial salvas sem nenhum trabalho adicional do lado do código de teste.

Aqui está o exemplo de código de teste que verifica se a aplicação web registra uma nova passkey no autenticador corretamente:

test('signup with passkey', async ({ page }) => { ... // Confirm there are currently no registered credentials const result1 = await client.send('WebAuthn.getCredentials', { authenticatorId }); expect(result1.credentials).toHaveLength(0); // Perform user actions to simulate creation of a passkey credential (e.g. user registration with passkey input) ... // Confirm the passkey was successfully registered const result2 = await client.send('WebAuthn.getCredentials', { authenticatorId }); expect(result2.credentials).toHaveLength(1); ... });

Combinando este trecho de código com os trechos da Seção 6.1, podemos testar o fluxo de inscrição em nossa página de demonstração. O vídeo a seguir é uma visualização do teste no modo de UI do Playwright:

6.3. Como Testar a Verificação de Passkey#

Verificar uma credencial de passkey com o autenticador virtual WebAuthn funciona de forma semelhante à criação de uma passkey, pois o autenticador virtual rastreia automaticamente o número de verificações realizadas usando uma credencial específica.

test('login with passkey', async ({ page }) => { ... // Confirm there is only one credential, and save its signCount const result1 = await client.send('WebAuthn.getCredentials', { authenticatorId }); expect(result1.credentials).toHaveLength(1); const signCount1 = result1.credentials[0].signCount; // Perform user actions to simulate verification of a passkey credential (e.g. login with passkey input) ... // Confirm the credential's new signCount is greater than the previous signCount const result2 = await client.send('WebAuthn.getCredentials', { authenticatorId }); expect(result2.credentials).toHaveLength(1); expect(result2.credentials[0].signCount).toBeGreaterThan(signCount1); ... });

O vídeo a seguir demonstra um teste para o fluxo de login em nossa página de demonstração:

6.4. Como Testar a Exclusão de Passkey#

Excluir uma passkey de uma aplicação web, por outro lado, não deve modificar nenhuma informação dentro do autenticador virtual WebAuthn. A aplicação web só deve ser capaz de excluir credenciais salvas em seu próprio servidor. Apenas o próprio usuário deve ser capaz de excluir consciente e manualmente uma credencial de passkey do autenticador virtual WebAuthn.

test('delete a registered passkey credential', async ({ page }) => { ... // Confirm there is currently one registered credential const result1 = await client.send('WebAuthn.getCredentials', { authenticatorId }); expect(result1.credentials).toHaveLength(1); // Perform user actions to simulate deletion of a passkey credential ... // Deleting a passkey credential from a website should not remove the credential from the authenticator const result2 = await client.send('WebAuthn.getCredentials', { authenticatorId }); expect(result2.credentials).toHaveLength(1); ... });

O vídeo a seguir demonstra um teste para a exclusão de uma credencial de passkey em nossa página de demonstração:

6.5. Como Simular Autenticação entre Dispositivos#

A maneira mais intuitiva de simular uma autenticação entre dispositivos a partir de um segundo dispositivo (que ainda não possui uma passkey registrada) é simplesmente adicionar uma nova instância do autenticador virtual WebAuthn através do comando CDP, assim:

test('signup with passkey', async ({ page }) => { ... // add a virtual authenticator for the first device const authenticatorId1 = await client.send('WebAuthn.addVirtualAuthenticator', { options }); // perform test actions of the first device ... // add a virtual authenticator for the second device const authenticatorId2 = await client.send('WebAuthn.addVirtualAuthenticator', { options }); // perform test actions of the second device .. });

Para evitar a complexidade de gerenciar os IDs de múltiplos autenticadores virtuais, também é possível simular um novo dispositivo simplesmente excluindo as credenciais de um único autenticador e adicionando-as de volta quando necessário:

test('signup with passkey', async ({ page }) => { ... const result = await client.send('WebAuthn.getCredentials', { authenticatorId }); const credential = result.credentials[0]; // assuming only one registered passkey const credentialId = credential.credentialId; await client.send('WebAuthn.removeCredential', { authenticatorId, credentialId }); // Perform test actions of the second device which doesn't have a registered passkey ... // Call if it's necessary to simulate the first device which has a registered passkey await client.send('WebAuthn.addCredential', { credential }); // Perform test actions of the first device ... });

Essa abordagem pode simplificar especialmente a implementação no caso em que um novo dispositivo precisa ser simulado, mas o dispositivo antigo não precisa mais ser usado. Nesse caso, você simplesmente precisa limpar as credenciais do autenticador virtual e descartá-las completamente:

test('signup with passkey', async ({ page }) => { ... const result = await client.send('WebAuthn.getCredentials', { authenticatorId }); const credential = result.credentials[0]; // assuming only one registered passkey const credentialId = credential.credentialId; await client.send('WebAuthn.clearCredentials', { authenticatorId }); // Perform test actions of the second device which doesn't have a registered passkey ... });

7. Alternativas ao Autenticador Virtual WebAuthn#

Explorar alternativas ao autenticador virtual WebAuthn pode oferecer flexibilidade na forma como os processos de autenticação com passkey / WebAuthn são testados dentro dos projetos.

7.1. Teste com Serviços de Simulação (Mock)#

Desenvolver serviços ou endpoints de simulação (mock) pode simular eficazmente o comportamento de autenticação, simplificando os testes ao abstrair as complexidades do mecanismo de autenticação real. Essa abordagem é particularmente benéfica quando serviços de autenticação externos estão em uso, permitindo que o foco permaneça na integração e funcionalidade dos componentes do sistema sem aprofundar nos detalhes da autenticação.

7.2. Teste de Integração com Autenticadores Reais#

Para um exame completo das funcionalidades de autenticação, o uso de autenticadores reais para testes de integração fornece uma visão detalhada da interação com chaves de segurança de hardware (por exemplo, YubiKeys) ou dispositivos biométricos (por exemplo, usados no Face ID, Touch ID ou Windows Hello). Embora normalmente conduzido manualmente devido à natureza complexa da integração de dispositivos do mundo real em testes automatizados, é viável desenvolver scripts de automação personalizados. Esses scripts podem conectar autenticadores reais com frameworks de teste de ponta a ponta, oferecendo uma aproximação mais próxima dos cenários de usuário reais e aumentando a confiabilidade do processo de autenticação em ambientes de produção.

8. Recomendações para Desenvolvedores#

Após demonstrar as diferentes opções e apresentar trechos de código específicos para testes E2E de passkeys / WebAuthn com Playwright, queremos também fornecer algumas recomendações mais gerais para desenvolvedores novos no assunto.

8.1. Estude o Cenário de Frameworks de Teste E2E#

Antes de mergulhar nos testes de passkeys ou de qualquer outro mecanismo de autenticação, é essencial avaliar os frameworks de teste E2E disponíveis e escolher a opção mais apropriada de acordo com os requisitos do seu projeto. Considere o equilíbrio entre a velocidade e a estabilidade oferecidas por frameworks baseados em CDP, como Playwright e Puppeteer, e a compatibilidade entre navegadores fornecida por frameworks baseados em WebDriver, como Selenium e Nightwatch. Embora os frameworks baseados em CDP ofereçam automação de navegador mais rápida e estável, eles são limitados a navegadores baseados em Chromium. Em contraste, os frameworks baseados em WebDriver fornecem uma compatibilidade mais ampla entre navegadores, incluindo suporte para navegadores não-Chromium como Firefox e Safari, embora com um desempenho potencialmente mais lento e menos estável. Entender esses equilíbrios ajudará você a tomar uma decisão informada e a selecionar o framework que melhor se adapta às necessidades do seu projeto.

8.2. Entenda os Conceitos Subjacentes ao WebAuthn e às Passkeys#

Embora o autenticador virtual WebAuthn simplifique o processo de teste de implementações de passkey, é crucial que os desenvolvedores tenham um sólido entendimento dos conceitos subjacentes ao padrão WebAuthn e às passkeys. Familiarize-se com as diferentes configurações disponíveis para o autenticador virtual WebAuthn, como protocol, transport, hasResidentKey, hasUserVerification e isUserVerified. Entender essas configurações permitirá que você ajuste o autenticador virtual para simular vários cenários de autenticação com precisão. Além disso, aprofunde-se nas complexidades da autenticação com passkey, incluindo sua integração com diferentes navegadores e dispositivos, bem como possíveis considerações de segurança. Esse conhecimento fundamental o capacitará a projetar estratégias de teste abrangentes e eficazes para a autenticação com passkey em suas aplicações web.

9. Resumo#

Este guia aprofundou o uso do autenticador virtual WebAuthn do CDP com o Playwright, destacando conceitos avançados e abordando questões não cobertas na documentação oficial. Também exploramos alternativas ao CDP dentro do Playwright e de outros frameworks de teste E2E. Apesar das implementações variadas, as especificações padronizadas do autenticador virtual WebAuthn garantem a relevância deste guia em diferentes protocolos de automação web e frameworks de teste de ponta a ponta. Para aprender mais a fundo sobre diferentes conceitos relacionados a passkeys, consulte nosso glossário de terminologias relevantes que podem ajudá-lo a ajustar o autenticador virtual WebAuthn com base em suas necessidades.

Add passkeys to your app in <1 hour with our UI components, SDKs & guides.

Start for free

Share this article


LinkedInTwitterFacebook

Enjoyed this read?

🤝 Join our Passkeys Community

Share passkeys implementation tips and get support to free the world from passwords.

🚀 Subscribe to Substack

Get the latest news, strategies, and insights about passkeys sent straight to your inbox.

Related Articles

Table of Contents