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 permettre à l'utilisateur de ne pas saisir de nom d'utilisateur. Cela permet aux utilisateurs de s'authentifier en sélectionnant un compte dans une liste de clés d'accès dont ils disposent pour le site Web actuel.
Les versions précédentes des clés de sécurité étaient conçues comme des méthodes d'authentification à deux facteurs et nécessitaient les ID des identifiants potentiels, ce qui obligeait à saisir un nom d'utilisateur. Les identifiants qu'une clé de sécurité peut trouver sans connaître leur ID sont appelés "identifiants visibles". La plupart des identifiants FIDO créés aujourd'hui sont 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 des identifiants.
Les parties de confiance (RP) 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 au moment de la création. Si l'utilisateur en sélectionne une, la valeur user.id
sera incluse dans la signature générée. 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électeur de compte, comme celles évoquées précédemment, n'affichent jamais d'identifiants non visibles.
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'
: Vous devez créer des identifiants détectables. Si elle ne peut pas être créée,NotSupportedError
est renvoyé.'preferred'
: le RP préfère créer des identifiants visibles, mais accepte des identifiants non visibles.'discouraged'
: le RP préfère créer des identifiants non visibles, mais accepte des identifiants visibles.
requireResidentKey
:
- Cette propriété est conservée pour la rétrocompatibilité avec le niveau 1 de WebAuthn, une ancienne version de la spécification. Définissez ce paramètre sur
true
si la valeur deresidentKey
est'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 avec une 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. Cette méthode 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 ce faire, omettez un tableau vide ou transmettez-lui le paramètre allowCredentials
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 avec une 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. Si l'utilisateur ne dispose pas de clés d'accès locales, la boîte de dialogue modale s'affiche toujours et lui propose de présenter une clé d'accès à partir d'un autre appareil. Lorsque vous passez à des clés d'accès pour vos utilisateurs, vous pouvez éviter d'utiliser cette interface utilisateur pour les utilisateurs qui n'en ont pas configuré.
À la place, 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 classique, en plus 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 disposant de paires nom d'utilisateur/mot de passe enregistrés peuvent les sélectionner, et les utilisateurs qui ne disposent ni de l'un ni de l'autre peuvent toujours saisir leur nom d'utilisateur et leur mot de passe.
Cette expérience utilisateur est idéale lorsque l'RP est en cours de migration et utilise à la fois des mots de passe et des clés d'accès.
Pour ce faire, 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 de navigator.credentials.get()
n'affiche aucune UI, mais si l'utilisateur met en surbrillance le champ de saisie annoté, toutes les clés d'accès disponibles sont incluses dans les options de saisie automatique. Si l'utilisateur en sélectionne une, il passera par la validation standard du déverrouillage de l'appareil. Ce n'est qu'à ce moment-là que la promesse renvoyée par .get()
se résout avec un résultat. Si l'utilisateur ne sélectionne pas de clé d'accès, la promesse n'est jamais résolue.
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 le remplissage automatique des formulaires, ainsi que l'atelier de programmation Implémenter des clés d'accès avec le remplissage automatique des formulaires dans une application Web.
Réauthentification
Dans certains cas, par exemple lorsque des clés d'accès sont utilisées 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 ou l'OS n'affichent un 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é) disposant d'identifiants valides.
Pour offrir cette expérience utilisateur, fournissez une liste d'ID d'identifiants pour l'utilisateur qui se connecte. Le RP doit pouvoir les interroger, car l'utilisateur est déjà connu. Fournissez les ID d'identifiants en tant qu'objets PublicKeyCredentialDescriptor
dans la propriété allowCredentials
du fichier 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 des identifiants de clé publique que le RP a obtenus lors de l'enregistrement de la clé d'accès.type
: ce champ est généralement'public-key'
.transports
: indice sur les transports compatibles avec l'appareil qui détient ces identifiants, utilisé par les navigateurs pour optimiser l'UI qui demande à l'utilisateur de présenter un appareil externe. Si elle est fournie, cette liste doit contenir le résultat de l'appel degetTransports()
lors de l'enregistrement de chaque identifiant.
Résumé
La visibilité des identifiants rend la procédure de connexion par clé d'accès beaucoup plus conviviale en leur permettant d'éviter de saisir un nom d'utilisateur. En combinant residentKey
, requireResidentKey
et allowCredentials
, les RP peuvent proposer des expériences de connexion qui :
- Affichez un sélecteur de compte modal.
- Afficher le remplissage automatique de formulaire pour les clés d'accès.
- Réauthentification.
Utilisez les identifiants détectables à bon escient. Vous pouvez ainsi concevoir des expériences de connexion par clé d'accès sophistiquées que les utilisateurs trouveront fluides et avec lesquelles ils seront plus susceptibles d'interagir.