Credential Manager - Verifier API

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 questo utente (ad esempio una patente di guida, un titolo accademico o attributi come età o indirizzo) o altri scenari in cui è necessario emettere e verificare una credenziale per attestare l'autenticità di un'entità.

Le credenziali digitali sono uno standard W3C pubblico che specifica come accedere alle credenziali digitali verificabili di un utente da un portafoglio digitale e viene implementato per i casi d'uso web con l'API Credential Management di W3C. Su Android, l'API DigitalCredential di Gestore delle credenziali viene utilizzata per verificare le credenziali digitali.

Implementazione

Per verificare le credenziali digitali nel tuo progetto Android:

  1. Aggiungi dipendenze allo script di build dell'app e inizializza una classe CredentialManager.
  2. Crea una richiesta di credenziali digitali e utilizzala per inizializzare un DigitalCredentialOption, quindi crea il GetCredentialRequest.
  3. Avvia il flusso getCredential con la richiesta creata per ricevere una risposta GetCredentialResponse 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)

Creare 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)
)

Ecco un esempio di richiesta OpenId4Vp. Un riferimento completo è disponibile su questo sito web.

{
  "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"
                  ]
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

Ottenere la credenziale

Avvia il flusso getCredential con la richiesta creata. Riceverai un GetCredentialResponse in caso di esito positivo o un GetCredentialException in caso di esito negativo.

Il flusso getCredential attiva le finestre di dialogo del sistema Android per presentare all'utente le opzioni di credenziali disponibili e raccogliere la sua selezione. Successivamente, l'app del portafoglio che contiene l'opzione delle credenziali scelta mostrerà le UI per raccogliere il consenso ed eseguire le azioni necessarie per generare una risposta delle 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.
        }
        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}")
    }
}