Ce guide explique comment demander des identifiants numériques à l'aide de Credential Manager dans une application Android qui utilise WebView. Utilisez un pont JavaScript pour faciliter la communication entre la page Web et l'application.
Présentation
Les étapes suivantes décrivent le cycle de vie d'une demande d'identifiant numérique à partir d'une WebView :
- Génération de la requête : la page Web de la WebView envoie une requête au serveur d'application, qui génère un fichier JSON de requête OpenID4VP et le renvoie.
- Lancement de la requête : la page Web utilise
navigator.credentials.get({ digital: ...}) pour demander des identifiants numériques à l'aide du fichier JSON de la requête. - Interception : le
bridge.jsinjecté intercepte cet appel, extrait le fichier JSON de la requête OpenID4VP spécifique et le transmet à l'application Android. - Gestion Android : l'application Android reçoit le message et appelle l'API
CredentialManager.getCredential. - Sélection de l'utilisateur : Credential Manager affiche une UI invitant l'utilisateur à partager ses identifiants. Les identifiants sont renvoyés à l'application Android.
- Réponse du pont : l'application Android renvoie la réponse à la page Web à l'aide du pont.
- Finalisation : la page Web reçoit et traite la réponse.
Prérequis
Avant d'implémenter le pont JavaScript pour les identifiants numériques dans WebView, assurez-vous que votre projet répond aux exigences suivantes :
- Compatibilité avec les versions d'Android : votre application doit cibler Android 6.0 (niveau d'API 23) ou version ultérieure.
- Contrôle de l'application hôte : vous devez contrôler l'application Android qui héberge le
WebViewafin de pouvoir associer unWebMessageListeneravant de charger la page Web. - HTTPS et frame de niveau supérieur : la page Web demandant l'identifiant doit être diffusée via
https://et s'exécuter dans le frame principal (isMainFramedoit êtretrue). Les sous-frames et les éléments<iframe>intégrés ne sont pas acceptés. - Activation de l'API expérimentale : l'API Digital Credentials étant expérimentale, vous devez annoter les classes ou les méthodes qui utilisent
GetDigitalCredentialOptionavec@OptIn(ExperimentalDigitalCredentialApi::class).
Ajouter des dépendances
Ajoutez les dépendances Credential Manager et AndroidX WebKit au fichier build.gradle.kts de votre module d'application :
dependencies {
// Credential Manager dependencies
implementation("androidx.credentials:credentials:1.7.0-alpha03")
implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")
// AndroidX WebKit (required for WebMessageListener bridge)
implementation("androidx.webkit:webkit:1.14.0")
}
Implémenter des identifiants numériques dans WebView
Vous devez ajouter du code JavaScript à votre WebView pour envoyer la demande d'identifiants et l'intercepter avec bridge.js.
Créer la requête JavaScript
Pour communiquer entre le code JavaScript exécuté dans une WebView et le code Android, injectez du code JavaScript dans votre WebView :
// Example digital credential request to request verified email
const request = {
"providers": [
{
"protocol": "openid4vp",
"request": JSON.stringify({
"requests": [
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "n-0S6_W_2F", // Generate dynamically
"dcql_query": {
"credentials": [
{
"id": "user_info_query",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["UserInfoCredential"]
},
"claims": [
{"path": ["email"]},
{"path": ["email_verified"]},
{"path": ["name"]}
]
}
]
}
}
}
]
})
}
]
};
try {
const credential = await navigator.credentials.get({
digital: request
});
// Process response
} catch (err) {
// Handle error
}
Créer le pont JavaScript
Créez un fichier nommé bridge.js ou injectez ce code à l'aide de evaluateJavascript.
Ce script remplace navigator.credentials.get pour intercepter la requête et envoyer la chaîne JSON OpenID4VP interne à l'application Android.
(function() {
if (!navigator.credentials) {
navigator.credentials = {};
}
const originalGet = navigator.credentials.get;
// Overrides navigator.credentials.get() to intercept W3C Digital Credential requests.
navigator.credentials.get = async function(options) {
if (options && options.digital) {
if (window.DigitalCredentialBridge) {
return new Promise((resolve, reject) => {
const digital = options.digital;
if (digital.providers && digital.providers.length > 0) {
const provider = digital.providers[0];
if (provider.protocol === "openid4vp") {
const requestJson = provider.request;
const message = {
type: "get",
request: requestJson
};
console.log("Sending message to native bridge:", JSON.stringify(message));
// Send the request string to native Android code
window.DigitalCredentialBridge.postMessage(JSON.stringify(message));
// Receive the response sent from native code using replyProxy.postMessage()
window.DigitalCredentialBridge.onmessage = function(event) {
console.log("Received response from native bridge:", event.data);
try {
const response = JSON.parse(event.data);
if (response.error) {
reject(new Error(response.error));
} else {
resolve(response);
}
} catch (e) {
// If it's not JSON, just resolve with the raw data
resolve(event.data);
}
};
} else {
reject(new Error("Unsupported protocol: " + provider.protocol));
}
} else {
reject(new Error("No providers specified in digital credential request"));
}
});
} else {
console.warn("DigitalCredentialBridge not found, falling back to original");
}
}
if (originalGet) {
return originalGet.call(navigator.credentials, options);
} else {
throw new Error("navigator.credentials.get is not supported and no bridge available");
}
};
})();
Implémenter des identifiants numériques dans Android
Configurez votre application Android pour qu'elle gère les demandes d'identifiants envoyées par bridge.js.
Créer l'écouteur Android
Configurez une classe DigitalCredentialWebListener qui implémente WebViewCompat.WebMessageListener. Cette classe gère les messages bidirectionnels entre JavaScript et le code Android natif, en appliquant des contrôles de sécurité sur isMainFrame et sourceOrigin, et en empêchant les requêtes qui se chevauchent.
Implémenter le gestionnaire Credential Manager
Appelez getCredential pour demander des identifiants numériques à l'appareil.
@OptIn(ExperimentalDigitalCredentialApi::class)
class CredentialManagerHandler(private val context: Context) {
private val credentialManager = CredentialManager.create(context)
suspend fun getDigitalCredential(requestJson: String): String {
val digitalCredentialOption = GetDigitalCredentialOption(requestJson)
val getCredRequest = GetCredentialRequest(listOf(digitalCredentialOption))
return try {
val result = credentialManager.getCredential(context, getCredRequest)
val credential = result.credential
if (credential is DigitalCredential) {
credential.credentialJson
} else {
"{\"error\": \"Unexpected credential type\"}"
}
} catch (e: GetCredentialException) {
"{\"error\": \"${e.message}\"}"
} catch (e: Exception) {
"{\"error\": \"Unknown exception\"}"
}
}
companion object {
private const val TAG = "CredManHandler"
}
}
Appliquer le framework à votre activité
Dans votre Activity ou View, enregistrez le WebMessageListener et les fonctions associées.
// Inside your Activity or View setup
AndroidView(
factory = { context ->
val handler = CredentialManagerHandler(context)
WebView(context).apply {
settings.javaScriptEnabled = true
// Register the bridge before loading URL
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
val listener = DigitalCredentialWebListener(coroutineScope, credentialManagerHandler)
WebViewCompat.addWebMessageListener(
webView,
INTERFACE_NAME,
setOf("*"),
listener
)
loadUrl("https://your-secure-domain.com/login")
}
},
)
Test du flux…
Testez le flux pour confirmer la communication entre la WebView et l'application Android. Le sélecteur d'identifiants s'affiche dans la WebView pendant le processus, et l'identifiant sélectionné est renvoyé à la WebView une fois l'opération terminée.