Passkeys : vers un Web sans mot de passe

Introduction : comprendre les passkeys en 5 minutes

Vous l’avez sans doute remarqué: malgré les gestionnaires de mots de passe et les authentifications à deux facteurs, la moindre création de compte en ligne se termine (encore) par une combinaison identifiant + mot de passe. Un procédé inventé en 1961… qui a surtout prouvé ses limites : réutilisation du même mot de passe, fuites massives de bases de données, hameçonnage (phishing) toujours plus sophistiqué (merci l'IA).

Les passkeys – standardisé par la FIDO Alliance et le W3C sous le nom WebAuthn/FIDO2 – proposent une alternative radicale : remplacer le mot de passe par une paire de clés asymétriques protégée par le matériel de l’appareil et déverrouillée par exemple par votre biométrie ou le code de l’appareil.

À la création, seule la clé publique part sur Internet ; à la connexion, la signature produite localement prouve que vous possédez la clé privée, sans jamais l’exposer. Résultat : aucune chaîne secrète à retenir, et rien à voler dans les bases de données des services. (paypal.com)

Concrètement, pour l’utilisateur final rien ne change à l’usage : sur un smartphone, il valide avec Face ID ou son empreinte ; sur un ordinateur, Windows Hello ou Touch ID font office de sésame. Pour le service en ligne, c’est l’assurance que l’identifiant est impossible à hameçonner et est unique. Google résume bien les bénéfices : « les passkeys offrent la protection la plus forte contre le phishing et sont huit fois plus rapides qu’un mot de passe + OTP (One Time Password) ». (support.google.com, microsoft.com)

Sous le capot : WebAuthn, CTAP et FIDO2

Le trio WebAuthn (côté navigateur), CTAP2 (côté authentificateur) et FIDO2 (ensemble de la norme) orchestre la magie :

  1. Enrôlement (attestation)
    • Le serveur génère un challenge aléatoire.
    • Le navigateur relaie la demande à l’authentificateur (module matériel, Secure Enclave, TPM…).
    • L’authentificateur crée une clé asymétrique (privée stockée localement, publique renvoyée).
    • Le serveur associe la clé publique au compte.
  2. Authentification (assertion)
    • Nouveau challenge → signature locale avec la clé privée.
    • Le serveur vérifie la signature avec la clé publique stockée.
    • Si le challenge est valide, l’utilisateur est connecté.

Aucun secret partagé, aucun mot de passe à hasher : la sécurité repose sur la cryptographie asymétrique et la protection matérielle de la clé privée.

Implémentation serveur : Symfony + WebAuthn Bundle

Pour la partie backend, nous avons choisi le WebAuthn/Symfony Bundle de Spomky‑Labs, mature et très documenté. (webauthn-doc.spomky-labs.com)

# Installation
composer require web-auth/webauthn-symfony-bundle

// .env
###> web-auth/webauthn-symfony-bundle ###
RELYING_PARTY_ID=localhost
RELYING_PARTY_NAME="DEMO PASSKEYS APP"
###< web-auth/webauthn-symfony-bundle ###

// config/packages/security.yaml
security:
    ...
    firewalls:
        main:
            provider: app_user_provider
            webauthn:
                secured_rp_ids:
                   - 'localhost'
                registration:
                    enabled: true
                authentication:
                    routes:
                        options_path: '/assertion/options'
                        result_path: '/assertion/result'
    ...
    

Astuce dev : Pour tester WebAuthn en HTTPS en local, un tunnel Ngrok fait parfaitement l’affaire :

$ ngrok http http://localhost:8080

En suivant la documentation pour la suite, rien d'insurmontable !Pour les plus curieux, lors du symfony Live Paris 2025 (après nos expérimentations), Rémi JANOT a fait une présentation avancée sur le sujet =>Passkeys pour une authentification fluide et sécurisée

Workflow complet

  1. Front – appel /webauthn/register/options → réception des options (challenge, rpId, etc.).
  2. Frontnavigator.credentials.create() → attestation.
  3. Front – POST des credentials vers /webauthn/register.
  4. Backend – validation du format + vérification de l’attestation.

La même logique s’applique à la connexion via /webauthn/login/options / /webauthn/login.

Intégration mobile

Android : Credential Manager et exemple Google

Depuis Android 14, le Credential Manager API prend en charge les passkeys de manière unifiée (autofill, gestion multi‑comptes, etc.), voir android.com. Google propose un sample très complet ; notre intégration s’est limitée à brancher les callbacks Java/Kotlin sur notre endpoint Symfony.

 val passkeysEligibility = PasskeysEligibility.isPasskeySupported(context)
if (!passkeysEligibility.isEligible) {
    return GenericCredentialManagerResponse.Error(errorMessage = passkeysEligibility.reason)
}

val result: GetCredentialResponse?
try {
    val credentialRequest = GetCredentialRequest(
        listOf(
            GetPublicKeyCredentialOption(
                creationResult.toString(),
                null,
            ),
            GetPasswordOption(),
        ),
    )
    result = credentialManager.getCredential(context, credentialRequest)
} catch (e: GetCredentialCancellationException) {
    // When credential selector bottom-sheet is cancelled
    return GenericCredentialManagerResponse.CancellationError
} catch (e: GetPublicKeyCredentialDomException) {
    // When the user verification / biometric bottom sheet is cancelled
    return GenericCredentialManagerResponse.CancellationError
} catch (e: Exception) {
    return GenericCredentialManagerResponse.Error(errorMessage = e.message ?: "")
}
return GenericCredentialManagerResponse.GetPasskeySuccess(getPasskeyResponse = result)

Aucun écueil particulier à signaler : le SDK gère le sélecteur de compte, la biométrie et la synchronisation des passkeys via Google Password Manager.

iOS : Oui mais...

Sur iOS 17/18, la création d’une passkey nécessite de jongler entre ASAuthorizationController, ASAuthorizationPlatformPublicKeyCredentialProvider, un validateur d’attestation et de la plomberie Swift. Apple annonce toutefois iOS 26 avec le nouveau ASAuthorizationAccountCreationProvider : une API unique qui encapsule l’enrôlement, la sauvegarde dans le trousseau iCloud et la synchronisation multi‑appareils. En l’absence de version stable, notre recommandation est d’attendre une version stable d'iOS 26 pour bénéficier d’un flux utilisateur cohérent et simplifié. (apple.com)

// Account creation @Environment(\.authorizationController) var authorizationController func performPasskeySignUp() async throws { let provider = ASAuthorizationAccountCreationProvider() let request = provider.createPlatformPublicKeyCredentialRegistrationRequest( acceptedContactIdentifiers: [.email, .phoneNumber], shouldRequestName: true, relyingPartyIdentifier: "example.com", challenge: try await fetchChallenge(), userID: try await fetchUserID() ) do { let result = try await authorizationController.performRequest(request) if case .passkeyAccountCreation(let account) = result { // Register new account on backend } } catch ASAuthorizationError .deviceNotConfiguredForPasskeyCreation { showPasswordSignUpForm = true } catch ASAuthorizationError.canceled { showPasswordSignUpForm = true } catch ASAuthorizationError.preferSignInWithApple { await performSignInWithApple() } catch { ... } }

PS: N'oubliez pas qu'Apple étant Apple, vous devez mettre en place côté backoffice une route pour votre fichier ASAA (/.well-known/apple-app-site-association) contenant à minima votre bundleID:

{
    'webcredentials': {
        'apps': ['TEAMID.com.passkey.sampleapp']
    }
}

Conclusion : un futur sans mot de passe

Google propose déjà la passkey comme méthode par défaut pour les comptes personnels ; Microsoft facilite l’ajout de passkeys dans Windows 11 ; PayPal ou eBay l’activent côté paiement (blog.google, microsoft.com, paypal.com) et en parallèle, Apple étend le support matériel et simplifie l’UX dans iOS 26.

Bref : tous les géants poussent dans la même direction : un Internet passwordless qui réduit drastiquement les risques d’hameçonnage et de fuites massives de données sensibles.

Chez Mobiapps, nous sommes convaincus que les passkeys représentent la prochaine révolution UX + sécurité. Vous envisagez de moderniser votre parcours d’authentification ? Parlons‑en !

Maxime Hermouet - Ingénieur études et développement Senior