Gli ID digitali possono essere accettati sia nei flussi in-app sia in quelli web. Per accettare le credenziali da Google Wallet, devi:
- Esegui l'integrazione utilizzando l'app o il web seguendo le istruzioni fornite.
- Utilizza l'ID test per testare il flusso utilizzando la sandbox di Google Wallet.
- Per pubblicare la tua soluzione, compila questo modulo per richiedere l'accesso e accettare i Termini di servizio delle credenziali Google Wallet. Devi compilare questo modulo per ciascuna delle tue entità aziendali. Il nostro team ti contatterà dopo che avrai compilato il modulo.
- Se hai domande, puoi contattare
wallet-identity-rp-support@google.com
.
Formati delle credenziali supportati
Esistono diversi standard proposti che definiscono il formato dei dati dei documenti di identità digitale, due dei quali stanno guadagnando una notevole popolarità nel settore:
- mdocs: definiti dalla norma ISO.
- Credenziali verificabili W3C: definite dal W3C.
Anche se Android Credential Manager supporta entrambi i formati, al momento Google Wallet supporta solo le identità digitali basate su mdoc.
Credenziali supportate
Google Wallet supporta due tipi di credenziali:
- Patente di guida digitale
- Tessera ID
Puoi richiedere una delle due credenziali nel flusso con una sola modifica del parametro.
Esperienza utente
Questa sezione descrive il flusso di presentazione online consigliato. Il flusso mostra la presentazione dell'età a un'app per la consegna di alcolici, ma l'esperienza utente è simile anche per il web e altri tipi di presentazioni.
![]() |
![]() |
![]() |
![]() |
![]() |
All'utente viene chiesto di verificare l'età nell'app o sul sito web | L'utente vede le credenziali idonee disponibili | L'utente visualizza la pagina di conferma in Google Wallet | L'utente esegue l'autenticazione per confermare la condivisione | Dati inviati all'app o al sito web |
Note chiave
- L'app o il sito web ha flessibilità nel modo in cui crea il punto di accesso all'API. Come mostrato nel passaggio 1, ti consigliamo di mostrare un pulsante generico come "Verifica con documento di identità digitale", poiché nel tempo prevediamo che saranno disponibili opzioni oltre a Google Wallet tramite l'API.
- La schermata del selettore nel passaggio 2 viene visualizzata da Android. Le credenziali idonee sono determinate da una corrispondenza tra la logica di registrazione fornita da ciascun Wallet e la richiesta inviata dalla relying party
- Il passaggio 3 viene eseguito da Google Wallet. Google Wallet mostrerà il nome, il logo e le norme sulla privacy forniti dallo sviluppatore in questa schermata.
Aggiungere un flusso di verifica dell'identità digitale
Se l'utente non dispone di una credenziale, ti consigliamo di fornire un link accanto al pulsante "Verifica con documento di identità digitale" che rimanda a Google Wallet per consentire all'utente di aggiungere un documento di identità digitale.
![]() |
![]() |
All'utente viene chiesto di verificare l'età nell'app o sul sito web | L'utente viene indirizzato a Google Wallet per ottenere un documento di identità digitale |
Nessun documento di identità digitale disponibile
Se l'utente seleziona l'opzione "Verifica con documento di identità digitale" senza disporre di un documento di identità digitale, verrà visualizzato questo messaggio di errore.
![]() |
![]() |
All'utente viene chiesto di verificare l'età nell'app o sul sito web | L'utente visualizza un errore se non dispone di un documento di identità digitale |
L'API non supporta una funzionalità per rilevare in modo silenzioso se l'utente dispone di ID digitali disponibili per preservare la privacy dell'utente. Pertanto, ti consigliamo di includere l'opzione del link di onboarding come mostrato.
Formato della richiesta per richiedere le credenziali di identità dal portafoglio
Di seguito è riportato un esempio di richiesta di mdoc requestJson
per ottenere le credenziali dell'identità
da qualsiasi portafoglio su un dispositivo Android o sul web.
{
"requests" : [
{
"protocol": "openid4vp",
"data": {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
Richiedi crittografia
client_metadata
contiene la chiave pubblica di crittografia per ogni richiesta.
Dovrai memorizzare le chiavi private per ogni richiesta e utilizzarle per autenticare
e autorizzare il token che ricevi dall'app Wallet.
Il parametro credential_request
in requestJson
è composto dai seguenti
campi.
{
"response_type": "vp_token",
"response_mode": "dc_api",
"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",
"alg" : "ECDH-ES",
}
]
},
"authorization_encrypted_response_alg": "ECDH-ES",
"authorization_encrypted_response_enc": "A128GCM"
}
}
Puoi richiedere un numero qualsiasi di attributi supportati da qualsiasi documento di identità memorizzato in Google Wallet.
In-app
Per richiedere le credenziali dell'identità dalle tue app per Android:
Aggiorna le dipendenze
In build.gradle del tuo progetto, aggiorna le dipendenze per utilizzare Gestore delle credenziali (beta):
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
// optional - needed for credentials support from play services, for devices running Android 13 and below.
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
Configurare Credential Manager
Per configurare e inizializzare un oggetto CredentialManager
, aggiungi una logica simile
alla seguente:
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
Richiedi attributi riguardanti l'identità
Anziché specificare singoli parametri per le richieste di identità, l'app li fornisce tutti insieme come stringa JSON all'interno di CredentialOption. Credential Manager trasmette questa stringa JSON ai portafogli digitali disponibili senza esaminarne i contenuti. Ogni portafoglio è quindi responsabile di: - Analizzare la stringa JSON per comprendere la richiesta di identità. - Determinare quali delle credenziali memorizzate, se presenti, soddisfano la richiesta.
Consigliamo ai partner di creare le richieste sul server anche per le integrazioni di app per Android.
utilizzerai requestJson
da Request Format
che include request
nella chiamata di funzione 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)
}
}
Verifica e convalida la risposta
Una volta ricevuta una risposta dal wallet, verificherai se la risposta è
andata a buon fine e contiene la risposta 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 risposta credentialJson
contiene un identityToken (JWT) criptato,
definito dal W3C. L'app Wallet è responsabile della creazione di questa risposta.
Esempio:
{
"protocol" : "openid4vp",
"data" : {
<encrpted_response>
}
}
Passerai questa risposta al server per convalidarne l'autenticità. Puoi trovare i passaggi per convalidare la risposta delle credenziali.
Web
Per richiedere le credenziali dell'identità utilizzando l'API Digital Credentials su Chrome, dovrai registrarti alla prova dell'origine dell'API Digital Credentials.
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
Invia la risposta di questa API al tuo server per convalidare la risposta delle credenziali
Passaggi per convalidare la risposta delle credenziali
Dopo aver ricevuto l'identityToken criptato dalla tua app o dal tuo sito web, devi eseguire diverse convalide prima di considerare attendibile la risposta.
Decripta la risposta utilizzando la chiave privata
Il primo passaggio consiste nel decriptare il token utilizzando la chiave privata salvata e ottenere un JSON di risposta.
Esempio Python:
from jwcrypto import jwe, jwk # Retrieve the Private Key from Datastore reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str) # 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
genererà un JSONvp_token
contenente la credenziale{ "vp_token": { "cred1": "<credential_token>" } }
Creare la trascrizione della sessione
Il passaggio successivo consiste nel creare SessionTranscript da ISO/IEC 18013-5:2021 con una struttura di trasferimento specifica per Android o il web:
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]
Per i trasferimenti su Android / web, devi utilizzare lo stesso nonce che hai utilizzato per generare
credential_request
.Android Handover
AndroidHandoverData = [ origin, // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>", clientId, // "android-origin:<app_package_name>", nonce, // nonce that was used to generate credential request ] AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
Trasferimento al browser
BrowserHandoverData =[ origin, // Origin URL clientId, // "web-origin:<origin>" nonce, // nonce that was used to generate credential request ] BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
Utilizzando
SessionTranscript
, la risposta del dispositivo deve essere convalidata in base alla clausola 9 della norma ISO/IEC 18013-5:2021. che include diversi passaggi, ad esempio:Controlla il certificato dell'emittente statale. Consulta i certificati IACA dell'emittente supportato.
Verifica della firma MSO (18013-5 Sezione 9.1.2)
Calcola e controlla i ValueDigest per gli elementi di dati (sezione 9.1.2 di 18013-5)
Verifica della firma
deviceSignature
(sezione 9.1.3 di 18013-5)
{
"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
}
Testare la soluzione
Per testare la tua soluzione, crea ed esegui la nostra applicazione Android di riferimento open source. Ecco i passaggi per creare ed eseguire l'app di riferimento:
- Clona il repository delle app di riferimento
- Apri il progetto in Android Studio.
- Crea ed esegui la destinazione
appholder
sul tuo dispositivo Android o emulatore.
Verifica basata su Zero Knowledge Proof (ZKP)
La prova a conoscenza zero (ZKP) è un metodo crittografico che consente a un individuo (il dimostratore) di dimostrare a un verificatore di possedere un determinato dato di identità o di soddisfare un criterio specifico (ad es. avere più di 18 anni, possedere una credenziale valida) senza rivelare i dati sottostanti effettivi. In sostanza, è un modo per confermare la veridicità di un'affermazione sulla propria identità mantenendo privati i dettagli sensibili.
I sistemi di identità digitale che si basano sulla condivisione diretta dei dati di identità spesso richiedono agli utenti di condividere informazioni personali eccessive, aumentando il rischio di violazioni dei dati e furto di identità. Le prove a conoscenza zero offrono un cambio di paradigma, consentendo la verifica con una divulgazione minima.
Concetti chiave delle prove a conoscenza zero nell'identità digitale:
- Prover: la persona che tenta di dimostrare un aspetto della propria identità.
- Verificatore: la persona giuridica che richiede la prova di un attributo di identità.
- La prova: un protocollo crittografico che consente al dimostratore di convincere il verificatore della veridicità della sua affermazione senza rivelare le informazioni segrete.
Proprietà principali delle prove zero-knowledge:
- Completezza: se l'affermazione è vera e sia il dimostratore che il verificatore sono onesti, il verificatore sarà convinto.
- Integrità: se l'affermazione è falsa, un dimostratore disonesto non può (con probabilità molto elevata) convincere un verificatore onesto che è vera.
- Zero-Knowledge: il verificatore non apprende nulla oltre al fatto che l'affermazione è vera. Non vengono esposti dati effettivi sull'identità del richiedente.
Per ricevere una prova Zero Knowledge da Google Wallet, devi modificare il
formato della richiesta in mso_mdoc_zk
e aggiungere zk_system_type
alla tua richiesta.
...
"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": "bd3168ea0a9096b4f7b9b61d1c210dac1b7126a9ec40b8bc770d4d485efce4e9", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 3
},
{
"system": "longfellow-libzk-v1",
"circuit_hash": "89288b9aa69d2120d211618fcca8345deb4f85d2e710c220cc9c059bbee4c91f", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 4
}
],
"verifier_message": "challenge"
},
"claims": [{
...
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
...
Riceverai una prova a conoscenza zero criptata dal wallet. Puoi
convalidare questa prova rispetto ai certificati IACA degli emittenti utilizzando
la libreria longfellow-zk di Google.
Per maggiori dettagli, puoi contattare l'indirizzo email dell'assistenza
wallet-identity-rp-support@google.com