Présentation
Cette section décrit la procédure pas à pas à suivre par les bureaux d'enregistrement de validateurs pour s'intégrer au service d'identité Google Wallet.
En tant qu'autorité d'enregistrement de validation (par exemple, une entreprise IDV qui effectue des validations pour le compte d'autres entités), vous agissez en tant qu'autorité de certification (CA) et signez les demandes d'identité pour les parties utilisatrices finales en aval que vous gérez.
Processus d'intégration
Étape 1 : Envoyez le formulaire d'ingestion et les certificats racines, et acceptez les conditions d'utilisation
Remplissez et envoyez le formulaire d'inscription pour les organismes d'enregistrement de validateurs. Dans ce formulaire, vous fournirez vos certificats racine de bac à sable et de production. En envoyant ce formulaire d'intégration, vous acceptez également formellement les Conditions d'utilisation de Google Wallet Verifier Registrar.
Étape 2 : Fiabilité et tests en bac à sable
Une fois que vous avez envoyé votre formulaire d'inscription, Google ajoute votre certificat racine du bac à sable au truststore du bac à sable Google Wallet et vous en informe. Vous pouvez ensuite commencer à tester votre intégration dans le bac à sable à l'aide de certificats signés par votre racine de bac à sable.
Étape 3 : Enregistrez une vidéo de démonstration de bout en bout
Une fois les tests dans le bac à sable terminés, enregistrez des démonstrations vidéo de bout en bout du processus de validation pour votre première partie de confiance et envoyez-les à Google.
- Exigences concernant la vidéo :
- Enregistrez des démonstrations pour les flux hébergés par le validateur (auto-hébergés) et hébergés par le marchand (hébergés par le fournisseur de services de paiement), le cas échéant.
- Utilisez les composants à afficher réels du marchand (nom, logo, URL des conditions d'utilisation) et de l'agrégateur dans les vidéos.
- Montrez clairement l'interface utilisateur et les écrans qui lancent le processus de validation.
Étape 4 : Approbation et établissement d'une relation de confiance avec la racine de production
Une fois que Google a reçu vos démonstrations vidéo de bout en bout, il lance le processus d'examen et d'approbation des vidéos tout en commençant en parallèle le processus d'approbation du certificat racine de production. Une fois les deux processus terminés et approuvés, vous pouvez commencer à lancer le service pour vos RP finaux en aval.
Étape 5 : Intégration continue des RP finaux
Pour chaque RP de fin que vous signez, vous devez :
- Informez Google : utilisez le formulaire d'intégration du client Verifier Registrar pour informer Google du nouveau RP et de son cas d'utilisation prévu.
- Configurer les métadonnées : renseignez les informations à afficher du RP (nom, logo, URL des règles de confidentialité) et définissez un nom unique et distinct (sujet) dans son certificat.
Spécifications techniques
A. Profil de certificat
Les requêtes doivent être signées par des certificats X.509 v3 standards générés à l'aide de P-256 / ECDSA et contenant une extension Google personnalisée :
- OID d'extension personnalisée :
1.3.6.1.4.1.11129.10.1 - Criticité : non critique.
- Contenu : hachage SHA256 de
RelyingPartyMetadataBytes, encodé dans unOCTET STRINGASN.1.
B. Schéma de métadonnées (CBOR)
Les métadonnées doivent être encodées au format CBOR.
; in CDDL for CBOR encoding
; schemaVersion = "v1"
RelyingPartyMetadataBytes = #6.24(bstr .cbor RelyingPartyMetadata)
RelyingPartyMetadata = {
"schema_version": tstr,
"display": DisplayInfo,
"aggregator_info": DisplayInfo ; Optional: include to show your branding alongside the RP
}
DisplayInfo = {
"display_name": tstr,
"logo_uri": tstr, ; See brand guidelines link in following paragraph
"privacy_policy_uri": tstr
}
Le logo_uri doit respecter les Consignes relatives à la marque Google Wallet.
C. Intégration OpenID4VP
Lorsque vous mettez en forme votre demande d'identifiant OpenID4VP signé, incluez les métadonnées encodées en base64url dans le champ gw_rp_metadata_bytes à l'intérieur de l'objet client_metadata (comme indiqué dans l'exemple de code de requête de la section suivante).
Conformité et révocation
- Surveillance des utilisations abusives : Google surveille les activités malveillantes liées aux RP et vous avertit en cas d'utilisation abusive détectée.
- Révocation rapide : vous devez révoquer rapidement les certificats des RP abusifs et publier une liste de révocation de certificats (CRL) mise à jour.
- Audit : Google conserve des journaux anonymisés pour s'assurer que les demandes RP correspondent à leurs cas d'utilisation enregistrés.
Étapes suivantes
Pour commencer votre intégration en tant que bureau d'enregistrement de validateurs, remplissez et envoyez le formulaire d'intégration des bureaux d'enregistrement de validateurs. Pour intégrer d'autres clients en aval, utilisez le formulaire d'intégration des clients du registre des validateurs.
Pour obtenir des réponses aux questions fréquentes sur l'intégration et l'intégration, consultez les questions fréquentes sur les identités et les identifiants numériques.
Détails de l'intégration du bureau d'enregistrement du validateur
La section suivante couvre les détails techniques de l'intégration pour les organismes d'enregistrement de l'outil de validation qui s'intègrent à l'API Digital Credentials (y compris le formatage et le chiffrement des requêtes, le déclenchement de l'API, la validation des réponses et l'implémentation des preuves à divulgation nulle de connaissance).
Formats et fonctionnalités compatibles
Google Wallet est compatible avec les pièces d'identité numériques basées sur la norme ISO mdoc.
- Identifiants acceptés : vous pouvez consulter les identifiants et attributs acceptés.
- Protocoles compatibles : OpenID4VP (version 1.0).
- SDK Android minimal : Android 9 (niveau d'API 28) ou version ultérieure.
- Navigateurs compatibles : pour obtenir la liste complète des navigateurs compatibles avec l'API Digital Credentials, consultez la page sur la compatibilité avec l'écosystème.
- Questions fréquentes : pour toute question concernant les pays acceptés et le calendrier des nouvelles régions, consultez les questions fréquentes sur les identifiants et les données.
Mettre en forme la demande
Pour demander des identifiants à partir d'un portefeuille, vous devez mettre en forme votre demande à l'aide d'OpenID4VP. Vous pouvez demander des identifiants spécifiques ou plusieurs identifiants dans un seul objet dcql_query.
Exemple de requête JSON
Voici un exemple de requête requestJson mdoc permettant d'obtenir des identifiants à partir de n'importe quel portefeuille sur un appareil Android ou sur le Web.
{
"requests" : [
{
"protocol": "openid4vp-v1-signed",
"data": {<signed_credential_request>} // This is an object, shouldn't be a string.
}
]
}
Demander le chiffrement
client_metadata contient la clé publique de chiffrement pour chaque requête.
Vous devrez stocker les clés privées pour chaque requête et les utiliser pour authentifier et autoriser le jeton que vous recevez de l'application de portefeuille.
Métadonnées OpenID4VP intégrées
Lorsque vous mettez en forme votre demande d'identifiants, vous devez inclure le champ gw_rp_metadata_bytes dans l'objet client_metadata (comme indiqué dans l'exemple de code de requête ci-dessous). Ce champ contient les métadonnées de la partie de confiance encodées en Base64URL requises par Google Wallet pour vérifier votre identité et afficher votre image de marque à l'utilisateur.
Le paramètre credential_request dans requestJson contient les champs suivants.
Certificat spécifique
{
"response_type": "vp_token",
"response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
"nonce": "1234",
"dcql_query": {
"credentials": [
{
"id": "cred1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL" // this is for mDL. Use com.google.wallet.idcard.1 for ID pass
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
}
]
},
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
"kty": "EC",
"crv": "P-256",
"x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
"y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
"use": "enc",
"kid" : "1", // This is required
"alg" : "ECDH-ES", // This is required
}
]
},
"vp_formats_supported": {
"mso_mdoc": {
"deviceauth_alg_values": [
-7
],
"issuerauth_alg_values": [
-7
]
}
},
"gw_rp_metadata_bytes": "<base64url encoded metadata string>"
}
}
Tout identifiant éligible
Voici un exemple de requête pour la mDL et le pass d'identité. L'utilisateur peut choisir l'une ou l'autre.
{
"response_type": "vp_token",
"response_mode": "dc_api.jwt", // change this to dc_api if you want to demo with a non encrypted response.
"nonce": "1234",
"dcql_query": {
"credentials": [
{
"id": "mdl-request",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
},
{ // Credential type 2
"id": "id_pass-request",
"format": "mso_mdoc",
"meta": {
"doctype_value": "com.google.wallet.idcard.1"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
],
"intent_to_retain": false // set this to true if you are saving the value of the field
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
],
"intent_to_retain": false
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
],
"intent_to_retain": false
}
]
}
]
credential_sets : [
{
"options": [
[ "mdl-request" ],
[ "id_pass-request" ]
]
}
]
},
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
"kty": "EC",
"crv": "P-256",
"x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
"y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
"use": "enc",
"kid" : "1", // This is required
"alg" : "ECDH-ES", // This is required
}
]
},
"vp_formats_supported": {
"mso_mdoc": {
"deviceauth_alg_values": [
-7
],
"issuerauth_alg_values": [
-7
]
}
},
"gw_rp_metadata_bytes": "<base64url encoded metadata string>"
}
}
Vous pouvez demander n'importe quel nombre d'attributs compatibles à partir de n'importe quel identifiant stocké dans Google Wallet.
Requêtes signées
Les requêtes signées (requêtes d'autorisation sécurisées par JWT) encapsulent votre demande de présentation vérifiable dans un jeton Web JSON (JWT) signé de manière cryptographique à l'aide de votre infrastructure PKI. Elles garantissent ainsi l'intégrité de la requête et prouvent votre identité à Google Wallet.
Prérequis
Avant d'implémenter les modifications de code pour les requêtes signées, assurez-vous d'avoir :
- Clé privée : vous avez besoin d'une clé privée (par exemple,
ES256à courbe elliptique) pour signer la requête gérée sur votre serveur. - Certificat : vous avez besoin d'un certificat X.509 standard dérivé de votre paire de clés.
- Enregistrement : assurez-vous que votre certificat public est enregistré auprès de Google Wallet.
Logique de construction des requêtes
Pour créer une requête, vous devez utiliser votre clé privée et encapsuler la charge utile dans un JWS.
def construct_openid4vp_request(
doctypes: list[str],
requested_fields: list[dict],
nonce_base64: str,
jwe_encryption_public_jwk: jwk.JWK,
is_zkp_request: bool,
is_signed_request: bool,
state: dict,
origin: str
) -> dict:
# ... [Existing logic to build 'presentation_definition' and basic 'request_payload'] ...
# ------------------------------------------------------------------
# SIGNED REQUEST IMPLEMENTATION (JAR)
# ------------------------------------------------------------------
if is_signed_request:
try:
# 1. Load the Verifier's Certificate
# We must load the PEM string into a cryptography x509 object
verifier_cert_obj = x509.load_pem_x509_certificate(
CERTIFICATE.encode('utf-8'),
backend=default_backend()
)
# 2. Calculate Client ID (x509_hash)
# We calculate the SHA-256 hash of the DER-encoded certificate.
cert_der = verifier_cert_obj.public_bytes(serialization.Encoding.DER)
verifier_fingerprint_bytes = hashlib.sha256(cert_der).digest()
# Create a URL-safe Base64 hash (removing padding '=')
verifier_fingerprint_b64 = base64.urlsafe_b64encode(verifier_fingerprint_bytes).decode('utf-8').rstrip("=")
# Format the client_id as required by the spec
client_id = f'x509_hash:{verifier_fingerprint_b64}'
# 3. Update Request Payload with JAR specific fields
request_payload["client_id"] = client_id
# Explicitly set expected origins to prevent relay attacks
# Format for android origin: origin = android:apk-key-hash:<base64SHA256_ofAppSigningCert>
# Format for web origin: origin = <origin_url>
if origin:
request_payload["expected_origins"] = [origin]
# 4. Create Signed JWT (JWS)
# Load the signing private key
signing_key = jwk.JWK.from_pem(PRIVATE_KEY.encode('utf-8'))
# Initialize JWS with the JSON payload
jws_token = jws.JWS(json.dumps(request_payload).encode('utf-8'))
# Construct the JOSE Header
# 'x5c' (X.509 Certificate Chain) is critical: it allows the wallet
# to validate your key against the one registered in the console.
x5c_value = base64.b64encode(cert_der).decode('utf-8')
protected_header = {
"alg": "ES256", # Algorithm (e.g., ES256 or RS256)
"typ": "oauth-authz-req+jwt", # Standard type for JAR
"kid": "1", # Key ID
"x5c": [x5c_value] # Embed the certificate
}
# Sign the token
jws_token.add_signature(
key=signing_key,
alg=None,
protected=json_encode(protected_header)
)
# 5. Return the Request Object
# Instead of returning the raw JSON, we return the signed JWT string
# under the 'request' key.
return {"request": jws_token.serialize(compact=True)}
except Exception as e:
print(f"Error signing OpenID4VP request: {e}")
return None
# ... [Fallback for unsigned requests] ...
return request_payload
Déclencher l'API
L'intégralité de la requête API doit être générée côté serveur. Selon la plate-forme, vous transmettrez le fichier JSON généré aux API de la plate-forme.
Dans l'application (Android)
Pour demander des identifiants d'identité depuis vos applications Android, procédez comme suit :
Mettre à jour les dépendances
Dans le fichier build.gradle de votre projet, mettez à jour vos dépendances pour utiliser le Credential Manager (bêta) :
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
Configurer le Gestionnaire d'identifiants
Pour configurer et initialiser un objet CredentialManager, ajoutez une logique semblable à celle-ci :
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
Demander des attributs d'identité
Au lieu de spécifier des paramètres individuels pour les requêtes d'identité, l'application les fournit tous ensemble sous forme de chaîne JSON dans CredentialOption.
Le Gestionnaire d'identifiants transmet cette chaîne JSON aux portefeuilles numériques disponibles sans examiner son contenu. Chaque portefeuille est ensuite responsable des éléments suivants :
- Analyser la chaîne JSON pour comprendre la demande d'identité.
- Déterminer lesquels de ses identifiants stockés, le cas échéant, répondent à la demande.
Nous recommandons aux partenaires de créer leurs requêtes sur le serveur, même pour les intégrations d'applications Android.
Vous utiliserez le requestJson de la section Format de la requête comme request dans l'appel de fonction GetDigitalCredentialOption().
// The request in the JSON format to conform with
// the JSON-ified Digital Credentials API request definition.
val requestJson = generateRequestFromServer()
val digitalCredentialOption =
GetDigitalCredentialOption(requestJson = requestJson)
// Use the option from the previous step to build the `GetCredentialRequest`.
val getCredRequest = GetCredentialRequest(
listOf(digitalCredentialOption)
)
coroutineScope.launch {
try {
val result = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
verifyResult(result)
} catch (e : GetCredentialException) {
handleFailure(e)
}
}
Gérer la réponse d'identifiant
Une fois que vous avez reçu une réponse du portefeuille, vérifiez si elle est positive et contient la réponse credentialJson.
// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
val credential = result.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson) // make a server call to validate the response
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential ${credential.type}")
}
}
}
// Handle failure.
fun handleFailure(e: GetCredentialException) {
when (e) {
is GetCredentialCancellationException -> {
// The user intentionally canceled the operation and chose not
// to share the credential.
}
is GetCredentialInterruptedException -> {
// Retry-able error. Consider retrying the call.
}
is NoCredentialException -> {
// No credential was available.
}
else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
}
}
La réponse credentialJson contient un identityToken (JWT) chiffré, défini par le W3C. L'application Wallet est responsable de la création de cette réponse.
Exemple :
{
"protocol" : "openid4vp-v1-signed",
"data" : {
<encrpted_response>
}
}
Vous renverrez cette réponse au serveur pour valider son authenticité. Vous trouverez la procédure de validation de la réponse d'identifiant.
Web
Pour demander des identifiants à l'aide de l'API Digital Credentials sur Chrome ou d'autres navigateurs compatibles, envoyez la requête suivante.
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp-v1-signed",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
Renvoyez la réponse de cette API à votre serveur pour valider la réponse des identifiants.
Valider la réponse
Une fois que le portefeuille renvoie le identityToken (JWT) chiffré, vous devez effectuer une validation stricte côté serveur avant de faire confiance aux données.
Déchiffrer la réponse
Utilisez la clé privée correspondant à la clé publique envoyée dans le client_metadata de la requête pour déchiffrer le JWE. Cela génère un vp_token.
Exemple Python :
from jwcrypto import jwe, jwk
# Retrieve the Private Key from Datastore
reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str)
# Save public key thumbprint for session transcript
encryption_public_jwk_thumbprint = reader_private_jwk.thumbprint()
# Decrypt the JWE encrypted response from Google Wallet
jwe_object = jwe.JWE()
jwe_object.deserialize(encrypted_jwe_response_from_wallet)
jwe_object.decrypt(reader_private_jwk)
decrypted_payload_bytes = jwe_object.payload
decrypted_data = json.loads(decrypted_payload_bytes)
decrypted_data génère un fichier JSON vp_token contenant les identifiants.
{
"vp_token":
{
"cred1": ["<base64UrlNoPadding_encoded_credential>"] // This applies to OpenID4VP 1.0 spec.
}
}
Créer la transcription de la session
L'étape suivante consiste à créer le SessionTranscript à partir de la norme ISO/IEC 18013-5:2021 avec une structure de transfert spécifique à Android ou au Web :
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]Pour les transferts Android et Web, vous devez utiliser le même nonce que celui utilisé pour générer
credential_request.Transfert Android
AndroidHandoverData = [ origin, // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>", nonce, // nonce that was used to generate credential request, encryption_public_jwk_thumbprint, // Encryption public key (JWK) Thumbprint ] AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
Transfert vers le navigateur
BrowserHandoverData =[ origin, // Origin URL nonce, // nonce that was used to generate credential request encryption_public_jwk_thumbprint, // Encryption public key (JWK) Thumbprint ] BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
À l'aide de
SessionTranscript, la réponse de l'appareil doit être validée conformément à la clause 9 de la norme ISO/IEC 18013-5:2021.Cette validation comprend plusieurs étapes :
Vérifiez le certificat de l'émetteur : extrayez la chaîne de certificats de signature de l'émetteur à partir de
issuerAuthet validez-la par rapport aux certificats racine IACA approuvés. Consultez les certificats IACA des émetteurs acceptés.Valider la signature du MSO (18013-5, section 9.1.2)
Calculer et vérifier
ValueDigestspour les éléments de données (section 9.1.2 de la norme 18013-5)Valider la signature
deviceSignature(18013-5, section 9.1.3)
{
"version": "1.0",
"documents": [
{
"docType": "org.iso.18013.5.1.mDL",
"issuerSigned": {
"nameSpaces": {...}, // contains data elements
"issuerAuth": [...] // COSE_Sign1 w/ issuer PK, mso + sig
},
"deviceSigned": {
"nameSpaces": 24(<< {} >>), // empty
"deviceAuth": {
"deviceSignature": [...] // COSE_Sign1 w/ device signature
}
}
}
],
"status": 0
}
Vérification de l'âge respectueuse de la confidentialité (ZKP)
Pour prendre en charge les preuves à divulgation nulle de connaissance (par exemple, pour vérifier qu'un utilisateur a plus de 18 ans sans connaître sa date de naissance exacte), définissez le format de votre requête sur mso_mdoc_zk et fournissez la configuration zk_system_type requise.
Pour obtenir une présentation générale de la preuve à divulgation nulle de connaissance et de ses capacités, consultez les questions fréquentes.
...
"dcql_query": {
"credentials": [{
"id": "cred1",
"format": "mso_mdoc_zk",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
"zk_system_type": [
{
"system": "longfellow-libzk-v1",
"circuit_hash": "f88a39e561ec0be02bb3dfe38fb609ad154e98decbbe632887d850fc612fea6f", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 5,
"block_enc_hash": 4096,
"block_enc_sig": 2945,
}
{
"system": "longfellow-libzk-v1",
"circuit_hash": "137e5a75ce72735a37c8a72da1a8a0a5df8d13365c2ae3d2c2bd6a0e7197c7c6", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 6,
"block_enc_hash": 4096,
"block_enc_sig": 2945,
}
],
"verifier_message": "challenge"
},
"claims": [{
...
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
...
Le portefeuille vous renverra une preuve à divulgation nulle de connaissance chiffrée. Vous pouvez valider cette preuve par rapport aux certificats IACA des émetteurs à l'aide de la bibliothèque longfellow-zk de Google.
Le service de validation contient un serveur Docker prêt au déploiement qui vous permet de valider la réponse par rapport à certains certificats IACA de l'émetteur.
Vous pouvez modifier certs.pem pour gérer les certificats d'émetteur IACA auxquels vous souhaitez faire confiance.
Ressources et assistance
- Questions fréquentes : pour obtenir des réponses aux questions fréquentes sur l'intégration technique, consultez les questions fréquentes sur les identités et les identifiants numériques.
- Mise en œuvre de référence : consultez notre mise en œuvre de référence des validateurs d'identité sur GitHub.
- Site Web de test : essayez le parcours de bout en bout sur verifier.multipaz.org.
- Spécification OpenID4VP : consultez la spécification technique pour openID4VP.
- Assistance : pour obtenir de l'aide concernant le débogage ou si vous avez des questions lors de l'intégration, contactez
wallet-identity-rp-support@google.com.