Gestire l'emissione delle credenziali con l'app del titolare

Per ricevere e archiviare le credenziali dagli emittenti, l'app del titolare deve gestire i flussi di emissione. L'emissione delle credenziali può essere attivata in due modi:

  • Flusso avviato dall'emittente: l'utente attiva una richiesta di emissione di una VDC da un'applicazione o un sito web dell'emittente. Ad esempio, un sito web può offrire ai suoi utenti l'opzione "Aggiungi il tuo passaporto al tuo wallet". L'emittente chiama l'API di emissione di Gestore delle credenziali per effettuare una richiesta di offerta di credenziali OpenID4VCI. Per gestire queste richieste, un titolare deve prima integrarsi con Gestore delle credenziali per registrare i propri metadati. Gestore delle credenziali mostrerà le opzioni pertinenti che l'utente potrà selezionare. Dopo che l'utente ha selezionato un'opzione di titolare, l'applicazione del titolare verrà richiamata e potrà procedere con i passaggi necessari per completare l'emissione.
  • Flusso avviato dal titolare: l'utente richiede di aggiungere una VDC dalla propria applicazione titolare. Ad esempio, un titolare potrebbe offrire un pulsante "Aggiungi il tuo passaporto". In questo caso, il titolare gestisce l'elenco degli emittenti supportati e i metadati. Non è necessario che si integri con Gestore delle credenziali di Android per completare questa funzione.

Per ulteriori informazioni su come funzionano le credenziali con l'API Holder, consulta Informazioni sulla memorizzazione delle credenziali digitali.

Compatibilità con le versioni di Android

L'API Holder è supportata su Android 6 (livello API 23) e versioni successive.

Implementazione

Per utilizzare l'API Holder di Gestore delle credenziali, aggiungi le seguenti dipendenze allo script di build del modulo dell'app:

Groovy

dependencies {
    // Use to implement credentials registrys

    implementation "androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-provider:1.0.0-alpha04"
    implementation "androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha04"

}

Kotlin

dependencies {
    // Use to implement credentials registrys

    implementation("androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-provider:1.0.0-alpha04")
    implementation("androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha04")

}

Crea RegistryManager

Crea un'istanza RegistryManager e registra una richiesta RegisterCreationOptionsRequest.

val registryManager = RegistryManager.create(context)

try {
    registryManager.registerCreationOptions(object :
        RegisterCreationOptionsRequest(
            creationOptions = buildIssuanceData(),
            matcher = loadIssuanceMatcher(),
            type = DigitalCredential.TYPE_DIGITAL_CREDENTIAL,
            id = "openid4vci",
        ) {}
    )
} catch (e: Exception) {
    Log.e(TAG, "Issuance registration failed.", e)
}

Il matcher è un file binario WebAssembly (Wasm) che riceve il creationOptions impostato durante la registrazione e l'offerta di credenziali inviata dall'emittente per determinare le voci visualizzate nell'interfaccia utente di Gestore delle credenziali. Per un esempio di matcher, consulta l'app wallet open source di esempio.

Gestisci una richiesta di emissione

Successivamente, il wallet deve gestire la selezione di un'opzione di creazione delle credenziali da parte dell'utente. Definisci un'attività che ascolta il filtro per intent androidx.credentials.registry.provider.action.CREATE_CREDENTIAL, come mostrato nel wallet di esempio.

L'intent che avvia l'attività contiene la richiesta di creazione e l'origine della chiamata, che puoi estrarre con la funzione PendingIntentHandler.retrieveProviderCreateCredentialRequest. L'API restituisce un ProviderCreateCredentialRequest contenente tutte le informazioni associate alla richiesta di creazione. I componenti chiave sono due:

  • L'app che ha effettuato la richiesta. Puoi recuperarlo con getCallingAppInfo.
  • La richiesta dell'app di chiamate. Puoi recuperarla con getCallingRequest, che restituisce un CreateCredentialRequest. Se la richiesta riguarda credenziali digitali, si tratta di un'istanza di CreateDigitalCredentialRequest, che contiene il file JSON della richiesta di emissione nella proprietà requestJson. Puoi elaborarlo con il seguente codice campione:
val pendingIntentRequest =
    PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)
val request = pendingIntentRequest!!.callingRequest
if (request is CreateDigitalCredentialRequest) {
    Log.i(TAG, "Got DC creation request: ${request.requestJson}")
    processCreationRequest(request.requestJson)
}

Attestazione di chiavi

Tieni presente quanto segue in merito all'attestazione di chiavi:

  • Quando generi un'attestazione di chiavi, potresti utilizzare BigInteger.toByteArray per convertire i materiali della chiave, ad esempio, in una chiave web JSON. Questo metodo a volte può aggiungere un byte di segno e causare un errore di convalida. In questo caso, rimuovi questi byte prima di inviare l'attestazione di chiavi all'emittente.
  • Ti consigliamo di utilizzare android_key_attestation come tipo di prova della chiave.

Restituisci la risposta di creazione

Una volta che il wallet ha completato i passaggi necessari per salvare la credenziale, termina l'attività con la risposta della credenziale:

val resultData = Intent()
PendingIntentHandler.setCreateCredentialResponse(
    resultData,
    CreateDigitalCredentialResponse(response.responseJson)
)
setResult(RESULT_OK, resultData)
finish()

Se si verifica un'eccezione, puoi inviare l'eccezione della credenziale in modo simile:

val resultData = Intent()
PendingIntentHandler.setCreateCredentialException(
    resultData,
    CreateCredentialUnknownException() // Configure the proper exception
)
setResult(RESULT_OK, resultData)
finish()

Per un esempio completo della restituzione della risposta della credenziale nel contesto, consulta l'app di esempio.