Connexion sans mot de passe WebAuthn
Doggy implémente l'authentification standard WebAuthn via web-auth/webauthn-symfony-bundle, avec prise en charge de la connexion par empreinte digitale, reconnaissance faciale et clé de sécurité.
Aperçu
Les informations d'identification WebAuthn sont stockées dans src/Entity/Security/WebauthnCredential.php (table webauthn_credentials), associées à App\Entity\Organization\Employee (l'entité utilisateur).
Le dépôt de certificats implémente PublicKeyCredentialSourceRepositoryInterface, avec prise en charge de l'enregistrement et de la consultation des informations d'identification WebAuthn.
Configuration
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']Configuration du pare-feu de sécurité
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'Gestion des informations d'identification
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; // 如 "Chrome on Mac"
#[ORM\ManyToOne(targetEntity: Employee::class, inversedBy: 'passkeys')]
private ?Employee $employee = null;
}Flux de connexion
Enregistrer un Passkey
- Après connexion, l'utilisateur accède aux paramètres de sécurité (
/user/webauthn/register/options) - Le navigateur appelle l'API WebAuthn pour créer les informations d'identification
- Le résultat est soumis à
/user/webauthn/register/result - Les informations d'identification à clé publique sont stockées dans la table
webauthn_credentials
Connexion sans mot de passe
- Saisissez le nom d'utilisateur et cliquez sur « Connexion Passkey »
- POST vers
/login/webauthn/optionspour obtenir le défi (challenge) - Le navigateur appelle l'API WebAuthn pour signer
- Le résultat est soumis à
/login/webauthn/result WebauthnSuccessHandlertraite la connexion réussie (enregistrement de l'appareil, mise à jour de l'horodatage)
Gestionnaire de succès
App\Security\WebauthnSuccessHandler, après une connexion réussie :
- Met à jour la date de dernière utilisation des informations d'identification
- Identifie automatiquement le nom de l'appareil (analyse du User-Agent)
- Vérifie s'il s'agit de la première connexion et guide vers la modification du mot de passe
- Prend en charge le flux de réinitialisation du mot de passe
Dépôt des informations d'identification WebAuthn
Implémentation de App\Repository\Security\WebauthnCredentialRepository :
findOneByCredentialId(): recherche les informations d'identificationfindAllForUserEntity(): récupère toutes les informations d'identification d'un utilisateursaveCredentialSource(): création/mise à jour des informations d'identificationparseUserAgent(): identification du nom de l'appareil