Bien que les identifiants FIDO tels que les clés d'accès visent à remplacer les mots de passe, la plupart d'entre eux peuvent également éviter à l'utilisateur de saisir un nom d'utilisateur. Cela permet aux utilisateurs de s'authentifier en sélectionnant un compte dans la liste des clés d'accès dont ils disposent pour le site Web actuel.
Les versions antérieures des clés de sécurité étaient conçues comme des méthodes d'authentification en deux étapes et nécessitaient les ID des identifiants potentiels, ce qui impliquait la saisie d'un nom d'utilisateur. Les identifiants qu'une clé de sécurité peut trouver sans connaître leurs ID sont appelés "identifiants visibles". La plupart des identifiants FIDO créés aujourd'hui sont des identifiants détectables, en particulier les clés d'accès stockées dans un gestionnaire de mots de passe ou sur une clé de sécurité moderne.
Pour vous assurer que vos identifiants sont créés en tant que clés d'accès (identifiants visibles), spécifiez residentKey et requireResidentKey lors de la création de l'identifiant.
Les parties de confiance peuvent utiliser des identifiants détectables en omettant allowCredentials lors de l'authentification par clé d'accès. Dans ce cas, le navigateur ou le système affiche à l'utilisateur une liste des clés d'accès disponibles, identifiées par la propriété user.name définie lors de la création. Si l'utilisateur en sélectionne un, la valeur user.id sera incluse dans la signature obtenue. Le serveur peut ensuite utiliser cet ID ou celui renvoyé pour rechercher le compte au lieu d'un nom d'utilisateur saisi.
Les UI de sélection de compte, comme celles dont nous avons parlé précédemment, n'affichent jamais d'identifiants non détectables.
requireResidentKey et residentKey
Pour créer une clé d'accès, spécifiez authenticatorSelection.residentKey et authenticatorSelection.requireResidentKey sur navigator.credentials.create() avec les valeurs indiquées ci-dessous.
async function register () {
// ...
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
residentKey :
'required': une identité numérique détectable doit être créée. Si le raccourci ne peut pas être créé,NotSupportedErrorest renvoyé.'preferred': le fournisseur de services préfère créer un identifiant visible, mais accepte un identifiant non visible.'discouraged': le RP préfère créer un identifiant non visible, mais accepte un identifiant visible.
requireResidentKey :
- Cette propriété est conservée pour la rétrocompatibilité avec WebAuthn niveau 1, une ancienne version de la spécification. Définissez cette valeur sur
truesiresidentKeyest'required', sinon définissez-la surfalse.
allowCredentials
Les RP peuvent utiliser allowCredentials sur navigator.credentials.get() pour contrôler l'expérience d'authentification par clé d'accès. Il existe généralement trois types d'expériences d'authentification par clé d'accès :
- Afficher un sélecteur de compte modal
- Afficher le remplissage automatique d'un formulaire de clé d'accès
- Réauthentification
Afficher un sélecteur de compte modal
Avec les identifiants détectables, les RP peuvent afficher un sélecteur de compte modal permettant à l'utilisateur de sélectionner un compte avec lequel se connecter, suivi de la validation de l'utilisateur. Cela convient au flux d'authentification par clé d'accès lancé en appuyant sur un bouton dédié à l'authentification par clé d'accès.
Pour offrir cette expérience utilisateur, omettez le paramètre allowCredentials ou transmettez-lui un tableau vide dans navigator.credentials.get().
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
Afficher le remplissage automatique d'un formulaire de clé d'accès
Le sélecteur de compte modal décrit ci-dessus fonctionne bien si la plupart des utilisateurs utilisent des clés d'accès et les ont disponibles sur l'appareil local. Pour un utilisateur qui n'a pas de clés d'accès locales, la boîte de dialogue modale s'affiche quand même et lui propose de présenter une clé d'accès depuis un autre appareil. Lorsque vous migrez vos utilisateurs vers les clés d'accès, vous pouvez éviter cette UI pour les utilisateurs qui n'en ont pas configuré.
Au lieu de cela, la sélection d'une clé d'accès peut être intégrée aux invites de saisie automatique pour les champs d'un formulaire de connexion traditionnel, à côté des noms d'utilisateur et mots de passe enregistrés. Ainsi, un utilisateur disposant de clés d'accès peut "remplir" le formulaire de connexion en sélectionnant sa clé d'accès, les utilisateurs ayant enregistré des paires nom d'utilisateur/mot de passe peuvent les sélectionner, et les utilisateurs ne disposant d'aucune de ces options peuvent toujours saisir leur nom d'utilisateur et leur mot de passe.
Cette expérience utilisateur est idéale lorsque le fournisseur de services est en cours de migration et utilise à la fois des mots de passe et des clés d'accès.
Pour offrir cette expérience utilisateur, en plus de transmettre un tableau vide à la propriété allowCredentials ou d'omettre le paramètre, spécifiez mediation: 'conditional' sur navigator.credentials.get() et annotez un champ de saisie HTML username avec autocomplete="username webauthn" ou un champ de saisie password avec autocomplete="password webauthn".
L'appel à navigator.credentials.get() n'entraîne l'affichage d'aucune UI, mais si l'utilisateur sélectionne le champ de saisie annoté, toutes les clés d'accès disponibles seront incluses dans les options de saisie automatique. Si l'utilisateur en sélectionne un, il devra passer par la procédure de validation de déverrouillage de l'appareil habituelle. Ce n'est qu'ensuite que la promesse renvoyée par .get() sera résolue avec un résultat. Si l'utilisateur ne sélectionne pas de clé d'accès, la promesse ne se résout jamais.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const cred = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
<input type="text" name="username" autocomplete="username webauthn" ...>
Pour découvrir comment créer cette expérience utilisateur, consultez Se connecter avec une clé d'accès via la saisie automatique des formulaires et l'atelier de programmation Implémenter des clés d'accès avec le remplissage automatique de formulaire dans une application Web.
Réauthentification
Dans certains cas, par exemple lors de l'utilisation de clés d'accès pour la réauthentification, l'identifiant de l'utilisateur est déjà connu. Dans ce cas, nous souhaitons utiliser une clé d'accès sans que le navigateur ni l'OS n'affichent de sélecteur de compte. Pour ce faire, transmettez une liste d'ID d'identifiants dans le paramètre allowCredentials.
Dans ce cas, si l'un des identifiants nommés est disponible localement, l'utilisateur est immédiatement invité à déverrouiller l'appareil. Dans le cas contraire, l'utilisateur est invité à présenter un autre appareil (un téléphone ou une clé de sécurité) contenant un identifiant valide.
Pour offrir cette expérience utilisateur, fournissez une liste des ID d'identifiants de l'utilisateur qui se connecte. Le RP doit pouvoir les interroger, car l'utilisateur est déjà connu. Fournissez des ID d'identifiants en tant qu'objets PublicKeyCredentialDescriptor dans la propriété allowCredentials de navigator.credentials.get().
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// Provide a list of PublicKeyCredentialDescriptors:
allowCredentials: [{
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, {
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, ...]
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
Un objet PublicKeyCredentialDescriptor se compose des éléments suivants :
id: ID de l'identifiant de clé publique que le RP a obtenu lors de l'enregistrement de la clé d'accès.type: ce champ est généralement défini sur'public-key'.transports: indication des transports compatibles avec l'appareil contenant ces identifiants, utilisée par les navigateurs pour optimiser l'UI qui demande à l'utilisateur de présenter un appareil externe. Si cette liste est fournie, elle doit contenir le résultat de l'appel degetTransports()lors de l'enregistrement de chaque identifiant.
Résumé
Les identifiants détectables rendent l'expérience de connexion par clé d'accès beaucoup plus conviviale, car ils permettent aux utilisateurs de ne pas avoir à saisir de nom d'utilisateur. En combinant residentKey, requireResidentKey et allowCredentials, les fournisseurs d'identité peuvent proposer des expériences de connexion qui :
- Afficher un sélecteur de compte modal.
- Afficher le remplissage automatique d'un formulaire de clé d'accès.
- Réauthentification.
Utilisez les identifiants détectables à bon escient. Vous pouvez ainsi concevoir des expériences de connexion sophistiquées avec des clés d'accès, que les utilisateurs trouveront fluides et avec lesquelles ils seront plus susceptibles d'interagir.