Avant que vos utilisateurs puissent s'authentifier avec des clés d'accès, votre application doit d'abord enregistrer ou créer la clé d'accès pour leur compte.
Pour créer la clé d'accès, obtenez les informations requises auprès du serveur de votre application, puis appelez l'API Credential Manager, qui renvoie une paire de clés publique et privée. La clé privée renvoyée est stockée dans un fournisseur d'identifiants, tel que le Gestionnaire de mots de passe de Google, en tant que clé d'accès. La clé publique est stockée sur le serveur de votre application.
Prérequis
Assurez-vous d'avoir configuré Digital Asset Links et de cibler les appareils équipés d'Android 9 (niveau d'API 28) ou version ultérieure.
Présentation
Ce guide se concentre sur les modifications requises dans votre application cliente Relying Party pour créer une clé d'accès. Il donne également un bref aperçu de l'implémentation du serveur de l'application Relying Party. Pour en savoir plus sur l'intégration côté serveur, consultez Enregistrer une clé d'accès côté serveur.
- Ajoutez des dépendances à votre application : ajoutez les bibliothèques Credential Manager requises.
- Instanciez Credential Manager : créez une instance Credential Manager.
- Obtenez les options de création d'identifiants à partir du serveur d'application : à partir de votre serveur d'application, envoyez à l'application cliente les informations requises pour créer la clé d'accès, comme des informations sur l'application, l'utilisateur, ainsi qu'un
challengeet d'autres champs. - Demander une clé d'accès : dans votre application, utilisez les informations reçues du serveur d'application pour créer un objet
GetPublicKeyCredentialOptionet utilisez cet objet pour appeler la méthodecredentialManager.getCredential()afin de créer une clé d'accès. - Gérez la réponse à la création de la clé d'accès : lorsque vous recevez les identifiants sur votre application cliente, vous devez encoder, sérialiser, puis envoyer la clé publique au serveur d'application. Vous devez également gérer chacune des exceptions qui peuvent se produire en cas de création d'une clé d'accès.
- Validez et enregistrez la clé publique sur le serveur : suivez les étapes côté serveur pour valider l'origine des identifiants, puis enregistrez la clé publique.
- Informer l'utilisateur : informez l'utilisateur que sa clé d'accès a été créée.
1. Ajouter des dépendances à votre application
Ajoutez les dépendances suivantes au fichier build.gradle du module de votre application :
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-beta03") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta03") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.6.0-beta03" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-beta03" }
2. Instancier le Gestionnaire d'identifiants
Utilisez le contexte de votre application ou de votre activité pour créer un objet CredentialManager.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
3. Obtenir les options de création d'identifiants à partir du serveur de votre application
Lorsque l'utilisateur clique sur un bouton "Créer une clé d'accès" ou lorsqu'un nouvel utilisateur s'inscrit, envoyez une requête depuis votre application vers votre serveur d'application pour obtenir les informations nécessaires au démarrage du processus d'enregistrement de la clé d'accès.
Utilisez une bibliothèque conforme à FIDO sur le serveur de votre application pour envoyer à votre application cliente les informations nécessaires à la création d'une clé d'accès, telles que des informations sur l'utilisateur, l'application et des propriétés de configuration supplémentaires. Pour en savoir plus, consultez Enregistrement des clés d'accès côté serveur.
Dans l'application cliente, décodez les options de création de clé publique envoyées par le serveur de l'application. Elles sont généralement représentées au format JSON. Pour en savoir plus sur le décodage pour les clients Web, consultez Encodage et décodage. Pour les applications clientes Android, vous devez gérer le décodage séparément.
L'extrait de code suivant montre la structure des options de création de clé publique envoyées par le serveur d'application :
{
"challenge": "<base64url-encoded challenge>",
"rp": {
"name": "<relying party name>",
"id": "<relying party host name>"
},
"user": {
"id": "<base64url-encoded user ID>",
"name": "<user name>",
"displayName": "<user display name>"
},
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
}
],
"attestation": "none",
"excludeCredentials": [
{
"id": "<base64url-encoded credential ID to exclude>",
"type": "public-key"
}
],
"authenticatorSelection": {
"requireResidentKey": true,
"residentKey": "required",
"userVerification": "required"
}
}
Voici les principaux champs des options de création de clé publique :
challenge: chaîne aléatoire générée par le serveur et utilisée pour empêcher les attaques par relecture.rp: informations sur l'application.rp.name: nom de l'application.rp.id: domaine ou sous-domaine de l'application.
user: informations sur l'utilisateur.id: ID unique de l'utilisateur. Cette valeur ne doit contenir aucune information permettant d'identifier personnellement l'utilisateur, comme une adresse e-mail ou un nom d'utilisateur. Vous pouvez utiliser une valeur aléatoire de 16 octets.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. S'il s'agit d'un nom d'utilisateur, spécifiez la même valeur que pour l'authentification par mot de passe.displayName: nom facultatif et convivial pour le compte, destiné à être affiché dans le sélecteur de compte.
authenticatorSelection: détails concernant l'appareil qui sera utilisé pour l'authentification.authenticatorAttachment: indique l'authentificateur préféré. Les valeurs possibles sont les suivantes : -platform: cette valeur est utilisée pour un authentificateur intégré à l'appareil de l'utilisateur, tel qu'un lecteur d'empreinte digitale. -cross-platform: cette valeur est utilisée pour les appareils en itinérance tels que les clés de sécurité. Il n'est généralement pas utilisé dans le contexte des clés d'accès. - Non spécifié (recommandé) : si vous ne spécifiez pas cette valeur, les utilisateurs pourront créer des clés d'accès sur leurs appareils préférés. Dans la plupart des cas, il est préférable de ne pas spécifier le paramètre.requireResidentKey: pour créer une clé d'accès, définissez la valeur du champBooleansurtrue.residentKey: pour créer une clé d'accès, définissez la valeur surrequired.userVerification: permet de spécifier les exigences relatives à la validation de l'utilisateur lors de l'enregistrement d'une clé d'accès. Les valeurs possibles sont les suivantes : -preferred: utilisez cette valeur si vous privilégiez l'expérience utilisateur par rapport à la protection, par exemple dans les environnements où la validation de l'utilisateur entraîne plus de friction que de protection. -required: utilisez cette valeur si l'appel d'une méthode de validation de l'utilisateur disponible sur l'appareil est requis. -discouraged: utilisez cette valeur si l'utilisation d'une méthode de validation de l'utilisateur est déconseillée.
Pour en savoir plus suruserVerification, consultez la présentation détaillée de userVerification.
excludeCredentials: répertoriez les ID d'identification dans un tableau pour empêcher la création d'une clé d'accès en double s'il en existe déjà une avec le même fournisseur d'identification.
4. Demander une clé d'accès
Après avoir analysé les options de création de clé publique côté serveur, créez une clé d'accès en encapsulant ces options dans un objet CreatePublicKeyCredentialRequest et en appelant createCredential().
createPublicKeyCredentialRequest inclut les éléments suivants :
requestJson: options de création d'identifiants envoyées par le serveur d'application.preferImmediatelyAvailableCredentials: champ booléen facultatif qui définit si vous préférez n'utiliser que des identifiants disponibles localement ou synchronisés avec un fournisseur d'identifiants pour traiter la requête, plutôt que des identifiants de clés de sécurité ou de flux de clés hybrides. Les utilisations possibles sont les suivantes :false(par défaut) : utilisez cette valeur si l'appel au Gestionnaire d'identifiants a été déclenché par une action explicite de l'utilisateur.true: utilisez cette valeur si le Gestionnaire d'identifiants est appelé de manière opportuniste, par exemple lors de la première ouverture de l'application.
Si vous définissez la valeur surtrueet qu'aucun identifiant n'est disponible immédiatement, le Gestionnaire d'identifiants n'affiche aucune UI et la requête échoue immédiatement, renvoyant NoCredentialException pour les demandes GET etCreateCredentialNoCreateOptionExceptionpour les requêtes de création.
origin: ce champ est défini automatiquement pour les applications Android. Pour les navigateurs et les applications privilégiées similaires qui doivent définirorigin, consultez Passer des appels du Gestionnaire d'identifiants au nom d'autres parties pour des applications privilégiées.isConditional: ce champ facultatif est défini surfalsepar défaut. Si vous définissez ce paramètre surtrueet qu'un utilisateur ne possède pas de clé d'accès, vous en créez automatiquement une en son nom la prochaine fois qu'il se connecte avec un mot de passe enregistré. La clé d'accès est stockée dans le fournisseur d'identifiants de l'utilisateur. La fonctionnalité de création conditionnelle nécessite la dernière version deandroidx.credentials.
L'appel de la fonction createCredential() lance l'UI de feuille inférieure intégrée du Gestionnaire d'identifiants, qui invite l'utilisateur à utiliser une clé d'accès et à sélectionner un fournisseur d'identifiants et un compte pour le stockage. Toutefois, si isConditional est défini sur true, l'UI de la feuille inférieure ne s'affiche pas et la clé d'accès est créée automatiquement.
5. Gérer la réponse
Une fois l'identité de l'utilisateur validée à l'aide du verrouillage de l'écran de l'appareil, une clé d'accès est créée et stockée dans le fournisseur d'identifiants sélectionné par l'utilisateur.
La réponse après un appel réussi de createCredential() est un objet PublicKeyCredential.
Le PublicKeyCredential se présente comme suit :
{
"id": "<identifier>",
"type": "public-key",
"rawId": "<identifier>",
"response": {
"clientDataJSON": "<ArrayBuffer encoded object with the origin and signed challenge>",
"attestationObject": "<ArrayBuffer encoded object with the public key and other information.>"
},
"authenticatorAttachment": "platform"
}
Dans l'application cliente, sérialisez l'objet et envoyez-le au serveur d'application.
Ajoutez du code pour gérer les échecs, comme indiqué dans l'extrait suivant :
fun handleFailure(e: CreateCredentialException) {
when (e) {
is CreatePublicKeyCredentialDomException -> {
// Handle the passkey DOM errors thrown according to the
// WebAuthn spec.
}
is CreateCredentialCancellationException -> {
// The user intentionally canceled the operation and chose not
// to register the credential.
}
is CreateCredentialInterruptedException -> {
// Retry-able error. Consider retrying the call.
}
is CreateCredentialProviderConfigurationException -> {
// Your app is missing the provider configuration dependency.
// Most likely, you're missing the
// "credentials-play-services-auth" module.
}
is CreateCredentialCustomException -> {
// You have encountered an error from a 3rd-party SDK. If you
// make the API call with a request object that's a subclass of
// CreateCustomCredentialRequest using a 3rd-party SDK, then you
// should check for any custom exception type constants within
// that SDK to match with e.type. Otherwise, drop or log the
// exception.
}
else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}")
}
}
6. Valider et enregistrer la clé publique sur le serveur d'application
Sur le serveur d'application, vous devez valider l'identifiant de clé publique, puis enregistrer la clé publique.
Pour vérifier l'origine des identifiants de clé publique, comparez-les à une liste d'autorisation d'applications approuvées. Si une clé a une origine non reconnue, rejetez-la.
Pour obtenir l'empreinte SHA-256 de l'application :
Imprimez le certificat de signature de votre application de version en exécutant la commande suivante dans un terminal :
keytool -list -keystore <path-to-apk-signing-keystore>Dans la réponse, identifiez l'empreinte SHA-256 du certificat de signature, mentionnée comme
Certificate fingerprints block:SHA256.Encodez l'empreinte SHA256 avec l'encodage base64url. Cet exemple Python montre comment encoder correctement l'empreinte digitale :
import binascii import base64 fingerprint = '<SHA256 finerprint>' # your app's SHA256 fingerprint print(base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))Ajoutez
android:apk-key-hash: au début du résultat de l'étape précédente pour obtenir un résultat semblable à ce qui suit :android:apk-key-hash:<encoded SHA 256 fingerprint>Le résultat doit correspondre à une origine autorisée sur le serveur de votre application. Si vous disposez de plusieurs certificats de signature, tels que des certificats de débogage et de publication, ou de plusieurs applications, répétez le processus et acceptez toutes les origines comme valides sur le serveur d'applications.
7. Informer l'utilisateur
Une fois la clé d'accès créée, informez vos utilisateurs qu'ils peuvent la gérer depuis l'application de leur fournisseur d'identifiants ou depuis les paramètres de l'application. Informez les utilisateurs à l'aide d'une boîte de dialogue, d'une notification ou d'une snackbar personnalisées. Étant donné qu'une création inattendue de clé d'accès par une entité malveillante nécessite une alerte de sécurité immédiate, envisagez de compléter ces méthodes intégrées à l'application par une communication externe, comme un e-mail.
Améliorer l'expérience utilisateur
Pour améliorer l'expérience utilisateur lors de l'implémentation de l'inscription avec le Gestionnaire d'identifiants, envisagez d'ajouter des fonctionnalités permettant de restaurer les identifiants et de supprimer les boîtes de dialogue de saisie automatique.
Ajouter une fonctionnalité pour restaurer les identifiants sur un nouvel appareil
Pour permettre aux utilisateurs de se connecter facilement à leurs comptes sur un nouvel appareil, implémentez la fonctionnalité Restaurer les identifiants. L'ajout d'identifiants de restauration avec BackupAgent permet aux utilisateurs de se connecter lorsqu'ils ouvrent votre application restaurée sur un nouvel appareil, ce qui leur permet de l'utiliser immédiatement.
Désactiver la saisie automatique dans les champs d'identifiants (facultatif)
Pour les écrans d'application où les utilisateurs sont censés utiliser l'UI de feuille inférieure de Credential Manager pour l'authentification, ajoutez l'attribut isCredential aux champs de nom d'utilisateur et de mot de passe. Cela empêche les boîtes de dialogue de saisie automatique (FillDialog et SaveDialog) de se chevaucher avec l'UI de la bottom sheet du Gestionnaire d'identifiants.
L'attribut isCredential est compatible avec Android 14 et les versions ultérieures.
L'exemple suivant montre comment ajouter l'attribut isCredential aux champs de nom d'utilisateur et de mot de passe concernés dans les vues appropriées de votre application :
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isCredential="true" />
Étapes suivantes
- Se connecter avec des clés d'accès
- Gérer les clés d'accès
- Comprendre les flux d'expérience utilisateur avec les clés d'accès