Créer une clé d'accès pour les connexions sans mot de passe

Les clés d'accès rendent les comptes utilisateur plus sûrs, plus simples et plus faciles à utiliser.

Publié le 12 octobre 2022, dernière mise à jour le 9 avril 2026

L'utilisation de clés d'accès renforce la sécurité, simplifie les connexions et remplace les mots de passe. Contrairement aux mots de passe classiques, que les utilisateurs doivent mémoriser et saisir manuellement, les clés d'accès utilisent les mécanismes de verrouillage de l'écran de l'appareil, comme les données biométriques ou les codes PIN. Elles réduisent les risques de hameçonnage et de vol d'identifiants.

Les clés d'accès se synchronisent sur tous les appareils à l'aide de fournisseurs de clés d'accès tels que le Gestionnaire de mots de passe de Google et le trousseau iCloud.

Vous devez créer une clé d'accès, stocker la clé privée de manière sécurisée auprès du fournisseur de clés d'accès, ainsi que les métadonnées nécessaires, et stocker sa clé publique sur votre serveur pour l'authentification. La clé privée émet une signature après la validation de l'utilisateur sur le domaine valide, ce qui rend les clés d'accès résistantes au hameçonnage. La clé publique valide la signature sans stocker d'identifiants sensibles, ce qui rend les clés d'accès résistantes au vol d'identifiants.

Comment créer une clé d'accès ?

Avant qu'un utilisateur puisse se connecter avec une clé d'accès, vous devez créer la clé d'accès, l'associer à un compte utilisateur et stocker sa clé publique sur votre serveur.

Vous pouvez demander aux utilisateurs de créer une clé d'accès dans l'une des situations suivantes :

  • Pendant ou après l'inscription.
  • Après vous être connecté.
  • Après vous être connecté à l'aide d'une clé d'accès depuis un autre appareil (c'est-à-dire que l'icône authenticatorAttachment est cross-platform).
  • Sur une page dédiée où les utilisateurs peuvent gérer leurs clés d'accès.

Pour créer une clé d'accès, vous utilisez l'API WebAuthn.

Le flux d'enregistrement d'une clé d'accès comporte quatre composants :

  • Backend : stocke les informations du compte utilisateur, y compris la clé publique.
  • Interface : communique avec le navigateur et récupère les données nécessaires auprès du backend.
  • Navigateur : exécute votre code JavaScript et interagit avec l'API WebAuthn.
  • Fournisseur de clés d'accès : crée et stocke la clé d'accès. Il s'agit généralement d'un gestionnaire de mots de passe tel que le Gestionnaire de mots de passe de Google ou d'une clé de sécurité.
Processus de création et d'enregistrement d'une clé d'accès
Processus de création et d'enregistrement d'une clé d'accès.

Avant de créer une clé d'accès, assurez-vous que le système répond aux conditions préalables suivantes :

  • Le compte utilisateur est validé par une méthode sécurisée (par exemple, par e-mail, par téléphone ou par fédération d'identité) dans un délai raisonnablement court.

  • Le frontend et le backend peuvent communiquer de manière sécurisée pour échanger des données d'identifiants.

  • Le navigateur est compatible avec WebAuthn et la création de clés d'accès.

Nous pouvons vous montrer comment vérifier la plupart d'entre eux dans les sections suivantes.

Une fois que le système remplit ces conditions, le processus suivant se déroule pour créer une clé d'accès :

  1. Le système déclenche le processus de création de clé d'accès lorsque l'utilisateur lance l'action (par exemple, en cliquant sur un bouton "Créer une clé d'accès" sur sa page de gestion des clés d'accès ou après avoir terminé son inscription).
  2. Le frontend demande les données d'identification nécessaires au backend, y compris les informations utilisateur, un défi et les ID d'identification pour éviter les doublons.
  3. L'interface appelle navigator.credentials.create() pour inviter le fournisseur de clé d'accès de l'appareil à générer une clé d'accès à l'aide des informations du backend. Notez que cet appel renvoie une promesse.
  4. L'appareil de l'utilisateur l'authentifie à l'aide d'une méthode biométrique, d'un code ou d'un schéma pour créer la clé d'accès.
  5. Le fournisseur de clés d'accès crée une clé d'accès et renvoie un identifiant de clé publique au frontend, ce qui résout la promesse.
  6. L'interface envoie l'identifiant de clé publique généré au backend.
  7. Le backend stocke la clé publique et d'autres données importantes pour l'authentification future.
  8. Le backend avertit l'utilisateur (par exemple, par e-mail) pour confirmer la création de la clé d'accès et détecter tout accès non autorisé potentiel.

Ce processus garantit un enregistrement sécurisé et fluide des clés d'accès pour les utilisateurs.

Compatibilités

La plupart des navigateurs sont compatibles avec WebAuthn, mais il existe quelques lacunes mineures. Pour en savoir plus sur la compatibilité avec les navigateurs et les systèmes d'exploitation, consultez passkeys.dev.

Créer une clé d'accès

Pour créer une clé d'accès, l'interface utilisateur doit suivre le processus suivant :

  1. Vérifiez la compatibilité.
  2. Récupérez des informations depuis le backend.
  3. Appelez l'API WebAuth pour créer une clé d'accès.
  4. Envoyez la clé publique renvoyée au backend.
  5. Enregistrez l'identifiant.

Les sections suivantes vous expliquent comment procéder.

Vérifier la compatibilité

Avant d'afficher un bouton "Créer une clé d'accès", le frontend doit vérifier les points suivants :

  • Le navigateur est compatible avec WebAuthn avec PublicKeyCredential.

Browser Support

  • Chrome: 67.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Source

  • Le navigateur est compatible avec la détection des fonctionnalités avec PublicKeyCredential.getClientCapabilities().

Browser Support

  • Chrome: 133.
  • Edge: 133.
  • Firefox: 135.
  • Safari: 17.4.

Source

  • Le navigateur est compatible avec l'interface utilisateur conditionnelle WebAuthn avec conditionalGet.

  • L'appareil est compatible avec un authentificateur de plate-forme (il peut créer une clé d'accès et s'authentifier sur l'appareil) avec passkeyPlatformAuthenticator.

L'extrait de code suivant montre comment vérifier la compatibilité avant d'afficher les options liées aux clés d'accès.

if (window.PublicKeyCredential && PublicKeyCredential.getClientCapabilities) {
  const capabilities = await PublicKeyCredential.getClientCapabilities();
  if (capabilities.conditionalGet === true &&
      capabilities.passkeyPlatformAuthenticator === true) {
    // The browser supports passkeys and the conditional UI.
  }
}

Dans cet exemple, le bouton Créer une clé d'accès ne doit s'afficher que si toutes les conditions sont remplies.

Récupérer des informations à partir du backend

Lorsque l'utilisateur clique sur le bouton, récupérez les informations requises à partir du backend pour appeler navigator.credentials.create().

L'extrait de code suivant présente un objet JSON contenant les informations requises pour appeler navigator.credentials.create() :

// Example `PublicKeyCredentialCreationOptions` contents
{
  challenge: *****,
  rp: {
    name: "Example",
    id: "example.com",
  },
  user: {
    id: *****,
    name: "john78",
    displayName: "John",
  },
  pubKeyCredParams: [{
    alg: -7, type: "public-key"
  },{
    alg: -257, type: "public-key"
  }],
  excludeCredentials: [{
    id: *****,
    type: 'public-key',
    transports: ['internal'],
  }],
  authenticatorSelection: {
    authenticatorAttachment: "platform",
    requireResidentKey: true,
  }
}

Les paires clé/valeur de l'objet contiennent les informations suivantes :

  • challenge : question d'authentification générée par le serveur dans ArrayBuffer pour cet enregistrement.
  • rp.id : Un ID RP (Relying Party ID), un domaine et un site Web peuvent spécifier leur domaine ou un suffixe enregistrable. Par exemple, si l'origine d'une RP est https://login.example.com:1337, l'ID de RP peut être login.example.com ou example.com. Si l'ID de RP est example.com, l'utilisateur peut s'authentifier sur login.example.com ou sur tout sous-domaine de example.com. Pour en savoir plus, consultez Autoriser la réutilisation des clés d'accès sur vos sites avec les requêtes d'origine associée.
  • rp.name : nom de la partie de confiance. Cette méthode est obsolète dans WebAuthn L3, mais elle est incluse pour des raisons de compatibilité.
  • user.id : ID utilisateur unique dans ArrayBuffer, généré lors de la création du compte. Il doit être permanent, contrairement à un nom d'utilisateur qui peut être modifié. L'ID utilisateur identifie un compte, mais ne doit pas contenir d'informations permettant d'identifier personnellement l'utilisateur. Vous disposez probablement déjà d'un ID utilisateur dans votre système, mais si nécessaire, créez-en un spécifiquement pour les clés d'accès afin de le préserver de toute information permettant d'identifier personnellement l'utilisateur.
  • user.name : identifiant unique du compte que l'utilisateur reconnaîtra, comme son adresse e-mail ou son nom d'utilisateur. Cet identifiant apparaîtra dans le sélecteur de comptes.
  • user.displayName : nom plus convivial et obligatoire pour le compte. Il ne doit pas nécessairement être unique. Il peut s'agir d'un nom choisi par l'utilisateur. Si vous ne disposez pas d'une valeur appropriée à inclure dans ce champ pour votre site, transmettez une chaîne vide. Ce nom peut s'afficher dans le sélecteur de compte selon le navigateur.
  • pubKeyCredParams : spécifie les algorithmes de clé publique acceptés par la RP (relying party). Nous vous recommandons de le définir sur [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}]. Il indique la compatibilité de l'algorithme ECDSA avec P-256 et RSA PKCS#1. Leur prise en charge vous permet de bénéficier d'une couverture complète.
  • excludeCredentials : liste des ID d'identifiants déjà enregistrés. Empêche l'enregistrement du même appareil à deux reprises en fournissant une liste des identifiants déjà enregistrés. Si le membre transports est fourni, il doit contenir le résultat de l'appel de getTransports() lors de l'enregistrement de chaque identifiant.
  • authenticatorSelection.authenticatorAttachment : définissez cette valeur sur "platform" avec hint: ['client-device'] si cette création de clé d'accès est une mise à niveau à partir d'un mot de passe, par exemple dans une promotion après une connexion. "platform" indique que le RP souhaite un authentificateur de plate-forme (un authentificateur intégré à l'appareil servant de plate-forme) qui ne demande pas, par exemple, d'insérer une clé de sécurité USB. L'utilisateur dispose d'une option plus simple pour créer une clé d'accès.
  • authenticatorSelection.requireResidentKey : Définissez-le sur une valeur booléenne true. Une clé d'accès détectable (clé résidente) stocke les informations utilisateur dans la clé d'accès et permet aux utilisateurs de sélectionner le compte lors de l'authentification.
  • authenticatorSelection.userVerification : indique si la validation de l'utilisateur à l'aide du verrouillage de l'écran de l'appareil est "required", "preferred" ou "discouraged". La valeur par défaut est "preferred", ce qui signifie que l'authentificateur peut ignorer la validation de l'utilisateur. Définissez ce paramètre sur "preferred" ou omettez la propriété.

Nous vous recommandons de créer l'objet sur le serveur, d'encoder ArrayBuffer avec Base64URL et de le récupérer à partir du frontend. Vous pouvez ainsi décoder la charge utile à l'aide de PublicKeyCredential.parseCreationOptionsFromJSON() et la transmettre directement à navigator.credentials.create().

L'extrait de code suivant montre comment récupérer et décoder les informations nécessaires à la création de la clé d'accès.

// Fetch an encoded `PubicKeyCredentialCreationOptions` from the server.
const _options = await fetch('/webauthn/registerRequest');

// Deserialize and decode the `PublicKeyCredentialCreationOptions`.
const decoded_options = JSON.parse(_options);
const options = PublicKeyCredential.parseCreationOptionsFromJSON(decoded_options);
...

Appeler l'API WebAuthn pour créer une clé d'accès

Appelez navigator.credentials.create() pour créer une clé d'accès. L'API renvoie une promesse, en attendant l'interaction de l'utilisateur qui affiche une boîte de dialogue modale.

Browser Support

  • Chrome: 60.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Source

// Invoke WebAuthn to create a passkey.
const credential = await navigator.credentials.create({
  publicKey: options
});

Envoyer l'identifiant de clé publique renvoyé au backend

Une fois l'utilisateur validé à l'aide du verrouillage de l'écran de l'appareil, une clé d'accès est créée et la promesse est résolue en renvoyant un objet PublicKeyCredential au frontend.

La promesse peut être refusée pour différentes raisons. Vous pouvez gérer ces erreurs en vérifiant la propriété name de l'objet Error :

  • InvalidStateError : une clé d'accès existe déjà sur l'appareil. Aucune boîte de dialogue d'erreur ne s'affiche pour l'utilisateur. Le site ne doit pas considérer cela comme une erreur. L'utilisateur souhaitait enregistrer l'appareil local, ce qui a été fait.
  • NotAllowedError : l'utilisateur a annulé l'opération.
  • AbortError : l'opération a été abandonnée.
  • Autres exceptions : une erreur inattendue s'est produite. Le navigateur affiche une boîte de dialogue d'erreur à l'utilisateur.

L'objet d'identifiant de clé publique contient les propriétés suivantes :

  • id : ID de la clé d'accès créée, encodé en Base64URL. Cet ID aide le navigateur à déterminer si une clé d'accès correspondante est enregistrée sur l'appareil au moment de l'authentification. Cette valeur doit être stockée dans la base de données sur le backend.
  • rawId : Version ArrayBuffer de l'ID des identifiants.
  • response.clientDataJSON : ArrayBuffer de données client encodées.
  • response.attestationObject : objet d'attestation encodé ArrayBuffer. Il contient des informations importantes telles qu'un ID de RP, des indicateurs et une clé publique.
  • authenticatorAttachment : renvoie "platform" lorsque cet identifiant est créé sur un appareil compatible avec les clés d'accès.
  • type : ce champ est toujours défini sur "public-key".

Encodez l'objet avec la méthode .toJSON(), sérialisez-le avec JSON.stringify(), puis envoyez-le au serveur.

...

// Encode and serialize the `PublicKeyCredential`.
const _result = credential.toJSON();
const result = JSON.stringify(_result);

// Encode and send the credential to the server for verification.  
const response = await fetch('/webauthn/registerResponse', {
  method: 'post',
  credentials: 'same-origin',
  body: result
});
...

Enregistrer l'identifiant

Après avoir reçu les identifiants de clé publique sur le backend, nous vous recommandons d'utiliser une bibliothèque ou une solution côté serveur au lieu d'écrire votre propre code pour traiter les identifiants de clé publique.

Vous pouvez ensuite stocker les informations récupérées à partir des identifiants dans la base de données pour une utilisation ultérieure.

La liste suivante inclut les propriétés recommandées à enregistrer :

  • ID d'identifiant : ID d'identifiant renvoyé avec l'identifiant de clé publique.
  • Nom du certificat : nom du certificat. Nommez-la d'après le fournisseur de clés d'accès qui l'a créée, qui peut être identifié en fonction de l'AAGUID.
  • ID utilisateur : ID utilisateur utilisé pour créer la clé d'accès.
  • Clé publique : clé publique renvoyée avec l'identifiant de clé publique. Cette valeur est requise pour valider une assertion de clé d'accès.
  • Date et heure de création : enregistrez la date et l'heure de création de la clé d'accès. Cela permet d'identifier la clé d'accès.
  • Date et heure de la dernière utilisation : enregistre la date et l'heure de la dernière utilisation de la clé d'accès par l'utilisateur pour se connecter. Cela permet de déterminer quelle clé d'accès l'utilisateur a utilisée (ou non).
  • AAGUID : Identifiant unique du fournisseur de clé d'accès.
  • Indicateur d'éligibilité à la sauvegarde : "true" si l'appareil est éligible à la synchronisation des clés d'accès. Ces informations aident les utilisateurs à identifier les clés d'accès synchronisables et celles liées à un appareil (non synchronisables) sur la page de gestion des clés d'accès.

Pour obtenir des instructions plus détaillées, consultez Enregistrement des clés d'accès côté serveur.

Signaler l'échec de l'enregistrement

Si l'enregistrement d'une clé d'accès échoue, cela peut dérouter l'utilisateur. S'il existe une clé d'accès chez le fournisseur de clés d'accès et qu'elle est disponible pour l'utilisateur, mais que la clé publique associée n'est pas stockée côté serveur, les tentatives de connexion à l'aide de la clé d'accès n'aboutiront jamais et il sera difficile de résoudre le problème. Si c'est le cas, veillez à l'en informer.

Pour éviter ce problème, vous pouvez signaler une clé d'accès inconnue au fournisseur de clés d'accès à l'aide de l'API Signal. En appelant PublicKeyCredential.signalUnknownCredential() avec un ID de RP et un ID d'identifiant, le RP peut informer le fournisseur de clés d'accès que l'identifiant spécifié a été supprimé ou n'existe pas. Il appartient au fournisseur de clés d'accès de décider comment traiter ce signal, mais si la fonctionnalité est prise en charge, la clé d'accès associée devrait être supprimée.

// Detect authentication failure due to lack of the credential
if (response.status === 404) {
  // Feature detection
  if (PublicKeyCredential.signalUnknownCredential) {
    await PublicKeyCredential.signalUnknownCredential({
      rpId: "example.com",
      credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
    });
  } else {
    // Encourage the user to delete the passkey from the password manager nevertheless.
    ...
  }
}

Pour en savoir plus sur l'API Signal, consultez Assurer la cohérence des clés d'accès avec les identifiants sur votre serveur avec l'API Signal.

Envoyer une notification à l'utilisateur

L'envoi d'une notification (par exemple, un e-mail) lorsqu'une clé d'accès est enregistrée aide les utilisateurs à détecter les accès non autorisés à leur compte. Si un pirate informatique crée une clé d'accès à l'insu de l'utilisateur, elle reste disponible pour de futurs abus, même après le changement de mot de passe. La notification alerte l'utilisateur et l'aide à éviter cela.

Checklist

  • Validez l'identité de l'utilisateur (de préférence par e-mail ou via une méthode sécurisée) avant de lui permettre de créer une clé d'accès.
  • Empêchez la création de clés d'accès en double pour le même fournisseur de clés d'accès à l'aide de excludeCredentials.
  • Enregistrez l'AAGUID pour identifier le fournisseur de clé d'accès et nommer l'identifiant pour l'utilisateur.
  • Signalez si une tentative d'enregistrement d'une clé d'accès échoue avec PublicKeyCredential.signalUnknownCredential().
  • Envoyez une notification à l'utilisateur après avoir créé et enregistré une clé d'accès pour son compte.

Ressources

Étape suivante : Se connecter avec une clé d'accès via le remplissage automatique de formulaire