La verifica delle credenziali digitali all'interno delle app per Android può essere utilizzata per autenticare e autorizzare l'identità di un utente (ad esempio un documento di identità ufficiale), le proprietà relative a quell'utente (ad esempio una patente di guida, un titolo di studio o attributi come l'età o l'indirizzo) o altri scenari in cui è necessario emettere e verificare una credenziale per confermare l'autenticità di un'entità.
L'API Verifier è supportata su Android 9 (livello API 28) e versioni successive.
Implementazione
Per verificare le credenziali digitali nel tuo progetto Android, segui questi passaggi:
- Aggiungi le dipendenze allo script di build dell'app e inizializza una classe
CredentialManager. - Crea una richiesta di credenziali digitali e utilizzala per inizializzare un
DigitalCredentialOption, quindi crea ilGetCredentialRequest. - Avvia il flusso
getCredentialcon la richiesta creata per ricevere unGetCredentialResponseriuscito o gestire eventuali eccezioni che potrebbero verificarsi. Una volta recuperata, convalida la risposta.
Aggiungi dipendenze e inizializza
Aggiungi le seguenti dipendenze allo script di build Gradle:
dependencies {
implementation("androidx.credentials:credentials:1.6.0-beta01")
implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta01")
}
Successivamente, inizializza un'istanza della classe CredentialManager.
val credentialManager = CredentialManager.create(context)
Crea una richiesta di credenziali digitali
Crea una richiesta di credenziali digitali e utilizzala per inizializzare un
DigitalCredentialOption.
// The request in the JSON format to conform with
// the JSON-ified Credential Manager - Verifier 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)
)
L'esempio seguente mostra una richiesta OpenId4Vp1. Per informazioni dettagliate sui campi di questa richiesta, consulta la documentazione di OpenID.
{
"requests": [
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "OD8eP8BYfr0zyhgq4QCVEGN3m7C1Ht_No9H5fG5KJFk",
"dcql_query": {
"credentials": [
{
"id": "cred1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
]
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
]
},
{
"path": [
"org.iso.18013.5.1",
"age_over_21"
]
}
]
}
]
}
}
}
]
}
Ottieni la qualifica
Avvia il flusso getCredential con la richiesta creata. Riceverai un messaggio GetCredentialResponse in caso di esito positivo o GetCredentialException se la richiesta non va a buon fine.
Il flusso getCredential attiva le finestre di dialogo del sistema Android per presentare le opzioni di credenziali disponibili per l'utente e raccogliere la sua selezione. Successivamente, l'app wallet
che contiene l'opzione di credenziale scelta mostrerà le UI per raccogliere il consenso
ed eseguire le azioni richieste per generare una risposta con credenziali digitali.
coroutineScope.launch {
try {
val result = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
verifyResult(result)
} catch (e : GetCredentialException) {
handleFailure(e)
}
}
// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
val credential = result.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson)
}
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}")
}
}
Richieste flessibili di più credenziali
L'API Digital Credentials supporta anche la richiesta di più tipi di credenziali contemporaneamente utilizzando OpenID4VP:
- Richieste simultanee: richiedi più credenziali in un'unica transazione utente. Ad esempio, un'app di viaggi può richiedere contemporaneamente una carta d'imbarco e un documento di identità ufficiale, consentendo all'utente di esaminarli e acconsentire a entrambi con un solo tocco.
- Flessibilità di evasione: accetta uno qualsiasi dei diversi tipi di credenziali o emittenti. Ad esempio, un flusso di verifica dell'età può accettare una patente di guida o un passaporto, consentendo agli utenti di soddisfare la richiesta utilizzando le credenziali memorizzate nel proprio holder.
Ecco un esempio di richiesta di più credenziali in un'unica richiesta:
{
"credentials": [
{
"id": "gov_id1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"age_over_21"
]
}
]
},
{
"id": "boarding_pass1",
"format": "dc+sd-jwt",
"meta": {
"vct_values": [
"https://credentials.example.airline/boarding-pass"
]
},
"claims": [
{
"path": [
"flight_number"
]
},
{
"path": [
"seat"
]
}
]
}
]
}
Gestisci la risposta
Dopo aver effettuato la richiesta di credenziali, gestisci l'oggetto GetCredentialResponse
restituito da CredentialManager.
// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
val credential = result.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson)
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential ${credential.type}")
}
}
}
Gestisci le eccezioni
La tua app deve gestire gli errori che possono essere generati, anche se non sono presenti credenziali sul dispositivo o se l'utente annulla l'operazione:
// 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.
}
is CreateCredentialUnknownException -> {
// An unknown, usually unexpected, error has occurred. Check the
// message error for any additional debugging information.
}
is CreateCredentialCustomException -> {
// You have encountered a custom error thrown by the wallet.
// If you made 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}")
}
}