Créez une expérience de connexion qui exploite les clés d'accès tout en gérant les utilisateurs de mot de passe existants.
Les clés d'accès remplacent les mots de passe et rendent les comptes utilisateur sur le Web plus sûrs, plus simples et plus faciles à utiliser. Toutefois, la transition de l'authentification par mot de passe à l'authentification par clé d'accès peut compliquer l'expérience utilisateur. L'utilisation de la saisie automatique dans les formulaires pour suggérer des clés d'accès peut contribuer à créer une expérience unifiée.
Pourquoi utiliser le remplissage automatique de formulaire pour se connecter avec une clé d'accès ?
Avec une clé d'accès, l'utilisateur peut se connecter à un site Web simplement en utilisant son empreinte digitale, son visage ou le code PIN de son appareil.
Idéalement, il n'y aurait pas d'utilisateurs de mots de passe, et le flux d'authentification pourrait être aussi simple qu'un seul bouton de connexion. Lorsque l'utilisateur appuie sur le bouton, une boîte de dialogue de sélecteur de compte s'affiche. L'utilisateur peut sélectionner un compte, déverrouiller l'écran pour valider et se connecter.
Toutefois, la transition de l'authentification par mot de passe à l'authentification par clé d'accès peut s'avérer difficile. À mesure que les utilisateurs passeront aux clés d'accès, certains continueront d'utiliser des mots de passe. Les sites Web devront donc s'adapter aux deux types d'utilisateurs. Les utilisateurs ne doivent pas être tenus de se souvenir sur quels sites ils sont passés aux clés d'accès. Demander aux utilisateurs de sélectionner la méthode à utiliser dès le départ serait donc une mauvaise expérience utilisateur.
Les clés d'accès sont également une nouvelle technologie. Expliquer ces fonctionnalités et s'assurer que les utilisateurs les utilisent facilement peut être un défi pour les sites Web. Nous pouvons nous appuyer sur des expériences utilisateur familières pour le remplissage automatique des mots de passe afin de résoudre ces deux problèmes.
UI conditionnelle
Pour offrir une expérience utilisateur efficace aux utilisateurs de clés d'accès et de mots de passe, vous pouvez inclure des clés d'accès dans les suggestions de saisie semi-automatique. Il s'agit de l'UI conditionnelle, qui fait partie de la norme WebAuthn.
Dès que l'utilisateur appuie sur le champ de saisie du nom d'utilisateur, une boîte de dialogue de suggestion de saisie automatique s'affiche, mettant en évidence les clés d'accès stockées ainsi que les suggestions de saisie automatique du mot de passe. L'utilisateur peut ensuite choisir un compte et utiliser le verrouillage de l'écran de l'appareil pour se connecter.
Les utilisateurs peuvent ainsi se connecter à votre site Web avec le formulaire existant comme si rien n'avait changé, mais avec l'avantage supplémentaire de sécurité des clés d'accès s'ils en ont une.
Fonctionnement
Pour vous authentifier à l'aide d'une clé d'accès, vous devez utiliser l'API WebAuthn.
Les quatre composants d'un flux d'authentification par clé d'accès sont les suivants :
- Backend: serveur backend qui contient la base de données des comptes qui stocke la clé publique et d'autres métadonnées sur la clé d'accès.
- Interface: votre interface qui communique avec le navigateur et envoie des requêtes de récupération au backend.
- Navigateur: navigateur de l'utilisateur qui exécute votre code JavaScript.
- Authentificateur: authentificateur de l'utilisateur qui crée et stocke la clé d'accès. Il peut s'agir du même appareil que le navigateur (par exemple, lorsque vous utilisez Windows Hello) ou d'un autre appareil, comme un téléphone.
- Dès qu'un utilisateur accède au front-end, il demande au backend une question d'authentification avec une clé d'accès et appelle
navigator.credentials.get()
pour lancer l'authentification avec une clé d'accès. Cette opération renvoie unPromise
. - Lorsque l'utilisateur place le curseur dans le champ de connexion, le navigateur affiche une boîte de dialogue de saisie automatique du mot de passe incluant les clés d'accès. Une boîte de dialogue d'authentification s'affiche si l'utilisateur sélectionne une clé d'accès.
- Une fois que l'utilisateur a validé son identité à l'aide du verrouillage de l'écran de l'appareil, la promesse est résolue et des identifiants de clé publique sont renvoyés au frontend.
- L'interface envoie les identifiants de clé publique au backend. Le backend vérifie la signature par rapport à la clé publique du compte correspondant dans la base de données. Si l'opération réussit, l'utilisateur est connecté.
S'authentifier avec une clé d'accès via le remplissage automatique de formulaire
Lorsqu'un utilisateur souhaite se connecter, vous pouvez effectuer un appel get
WebAuthn conditionnel pour indiquer que des clés d'accès peuvent être incluses dans les suggestions de saisie automatique. Un appel conditionnel à l'API navigator.credentials.get()
de WebAuthn n'affiche pas l'UI et reste en attente jusqu'à ce que l'utilisateur sélectionne un compte avec lequel se connecter parmi les suggestions de saisie automatique. Si l'utilisateur choisit une clé d'accès, le navigateur résout la promesse avec des identifiants plutôt que de remplir le formulaire de connexion. Il est ensuite de la responsabilité de la page de connecter l'utilisateur.
Annoter un champ de saisie de formulaire
Ajoutez un attribut autocomplete
au champ input
du nom d'utilisateur, si nécessaire.
Ajoutez username
et webauthn
comme jetons pour lui permettre de suggérer des clés d'accès.
<input type="text" name="username" autocomplete="username webauthn" ...>
Détection de fonctionnalités
Avant d'appeler un appel d'API WebAuthn conditionnel, vérifiez les points suivants:
- Le navigateur est compatible avec WebAuthn avec
PublicKeyCredential
.
- Le navigateur est compatible avec l'UI conditionnelle WebAuthn avec
PublicKeyCredential.isConditionalMediationAvailable()
.
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if conditional mediation is available.
const isCMA = await PublicKeyCredential.isConditionalMediationAvailable();
if (isCMA) {
// Call WebAuthn authentication
}
}
Récupérer une question d'authentification auprès du serveur RP
Récupérez un défi auprès du serveur RP requis pour appeler navigator.credentials.get()
:
challenge
: défi généré par le serveur dans un ArrayBuffer. Ce paramètre est nécessaire pour éviter les attaques par rejeu. Veillez à générer un nouveau défi à chaque tentative de connexion et à l'ignorer après un certain délai ou après l'échec de la validation d'une tentative de connexion. Considérez-le comme un jeton CSRF.allowCredentials
: tableau d'identifiants acceptés pour cette authentification. Transmettez un tableau vide pour permettre à l'utilisateur de sélectionner une clé d'accès disponible dans une liste affichée par le navigateur.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 cette valeur sur"preferred"
ou omettez la propriété.
Appeler l'API WebAuthn avec l'indicateur conditional
pour authentifier l'utilisateur
Appelez navigator.credentials.get()
pour commencer à attendre l'authentification de l'utilisateur.
// To abort a WebAuthn call, instantiate an `AbortController`.
const abortController = new AbortController();
const publicKeyCredentialRequestOptions = {
// Server generated challenge
challenge: ****,
// The same RP ID as used during registration
rpId: 'example.com',
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
rpId
: un ID de RP est un domaine, et un site Web peut spécifier son propre domaine ou un suffixe enregistrable. Cette valeur doit correspondre à l'ID rp utilisé lors de la création de la clé d'accès.
N'oubliez pas de spécifier mediation: 'conditional'
pour rendre la requête conditionnelle.
Envoyer les identifiants de clé publique renvoyés au serveur RP
Une fois que l'utilisateur a sélectionné un compte et donné son consentement à l'aide du verrouillage de l'écran de l'appareil, la promesse est résolue et renvoie un objet PublicKeyCredential
au frontend de la RP.
Une promesse peut être refusée pour plusieurs raisons. Vous devez gérer les erreurs en conséquence, en fonction de la propriété name
de l'objet Error
:
NotAllowedError
: l'utilisateur a annulé l'opération.- 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 authentifiée, encodé en base64url.rawId
: version ArrayBuffer de l'ID d'identifiant.response.clientDataJSON
: ArrayBuffer de données client. Ce champ contient des informations telles que la question d'authentification et l'origine que le serveur de la RP doit vérifier.response.authenticatorData
: ArrayBuffer de données d'authentificateur. Ce champ contient des informations telles que l'ID de RP.response.signature
: ArrayBuffer de la signature. Cette valeur est l'élément central de l'identifiant et doit être validée sur le serveur.response.userHandle
: ArrayBuffer contenant l'ID utilisateur défini au moment de la création. Cette valeur peut être utilisée à la place de l'identifiant si le serveur a besoin de choisir les valeurs d'identification qu'il utilise ou si le backend souhaite éviter la création d'un index sur les identifiants.authenticatorAttachment
: renvoieplatform
lorsque cet identifiant provient de l'appareil local. Sinon,cross-platform
, en particulier lorsque l'utilisateur se connecte à l'aide d'un téléphone. Si l'utilisateur a dû utiliser un téléphone pour se connecter, envisagez de l'inviter à créer une clé d'accès sur l'appareil local.type
: ce champ est toujours défini sur"public-key"
.
Si vous utilisez une bibliothèque pour gérer l'objet d'identifiant de clé publique sur le serveur RP, nous vous recommandons d'envoyer l'objet entier au serveur après l'avoir encodé partiellement avec base64url.
Vérifier la signature
Lorsque vous recevez les identifiants de clé publique sur le serveur, transmettez-les à la bibliothèque FIDO pour traiter l'objet.
Recherchez l'ID d'identifiant correspondant à l'aide de la propriété id
(si vous devez déterminer le compte utilisateur, utilisez la propriété userHandle
, qui correspond à l'user.id
que vous avez spécifiée lors de la création des identifiants). Vérifiez si l'signature
des identifiants peut être validée avec la clé publique stockée. Pour ce faire, nous vous recommandons d'utiliser une bibliothèque ou une solution côté serveur plutôt que d'écrire votre propre code. Vous trouverez des bibliothèques Open Source dans le dépôt GitHub awesome-webauth.
Une fois les identifiants validés à l'aide d'une clé publique correspondante, connectez l'utilisateur.
Pour obtenir des instructions plus détaillées, consultez Authentification par clé d'accès côté serveur.