Início de sessão sem palavra-passe WebAuthn
O Doggy implementa autenticação padrão WebAuthn baseada em web-auth/webauthn-symfony-bundle, com suporte para início de sessão com impressão digital, reconhecimento facial e chaves de segurança.
Visão geral
As credenciais WebAuthn são armazenadas em src/Entity/Security/WebauthnCredential.php (tabela webauthn_credentials), associadas a App\Entity\Organization\Employee (a entidade de utilizador).
O repositório de credenciais implementa PublicKeyCredentialSourceRepositoryInterface, com suporte para guardar e consultar credenciais WebAuthn.
Configuração
yaml
# config/packages/webauthn.yaml
webauthn:
credential_repository: 'App\Repository\Security\WebauthnCredentialRepository'
user_repository: 'App\Repository\Organization\EmployeeRepository'
creation_profiles:
default:
rp:
name: '%env(RELYING_PARTY_NAME)%'
id: '%env(RELYING_PARTY_ID)%'
public_key_credential_parameters:
- -7 # ES256
- -257 # RS256
authenticator_selection_criteria:
resident_key: required
user_verification: required
request_profiles:
default:
rp_id: '%env(RELYING_PARTY_ID)%'
user_verification: required
allowed_origins: ['http://localhost:8000']Configuração do firewall de segurança
yaml
# config/packages/security.yaml
security:
firewalls:
main:
custom_authenticator: App\Security\AppCustomAuthenticator
webauthn:
success_handler: App\Security\WebauthnSuccessHandler
authentication:
enabled: true
routes:
options_path: '/login/webauthn/options'
result_path: '/login/webauthn/result'Gestão de credenciais
php
// src/Entity/Security/WebauthnCredential.php
class WebauthnCredential
{
private string $publicKeyCredentialId;
private string $type; // 'public-key'
private array $transports; // ['usb', 'nfc', 'internal']
private string $attestationType;
private string $credentialPublicKey;
private string $userHandle; // Employee ID
private int $counter;
private ?string $deviceName; // ex.: "Chrome on Mac"
#[ORM\ManyToOne(targetEntity: Employee::class, inversedBy: 'passkeys')]
private ?Employee $employee = null;
}Fluxo de início de sessão
Registar um Passkey
- Após o início de sessão, o utilizador acede às definições de segurança (
/user/webauthn/register/options) - O browser invoca a API WebAuthn para criar a credencial
- O resultado é submetido em
/user/webauthn/register/result - A credencial de chave pública é armazenada na tabela
webauthn_credentials
Início de sessão sem palavra-passe
- Introduzir o nome de utilizador e clicar em «Iniciar sessão com Passkey»
- POST para
/login/webauthn/optionspara obter o desafio - O browser invoca a API WebAuthn para assinar
- O resultado é submetido em
/login/webauthn/result WebauthnSuccessHandlertrata do início de sessão bem-sucedido (regista o dispositivo, atualiza a hora)
Processador de sucesso
App\Security\WebauthnSuccessHandler, após o início de sessão bem-sucedido:
- Atualiza a hora da última utilização da credencial
- Identifica automaticamente o nome do dispositivo (análise do User-Agent)
- Verifica se é o primeiro início de sessão e orienta a alteração da palavra-passe
- Suporta o fluxo de redefinição de palavra-passe
Repositório de credenciais WebAuthn
App\Repository\Security\WebauthnCredentialRepository implementa:
findOneByCredentialId(): consulta uma credencialfindAllForUserEntity(): obtém todas as credenciais do utilizadorsaveCredentialSource(): cria/atualiza credenciaisparseUserAgent(): identificação do nome do dispositivo