Credential Manager – Verifier API

Die Überprüfung digitaler Anmeldedaten in Android-Apps kann verwendet werden, um die Identität eines Nutzers (z. B. einen amtlichen Ausweis), Eigenschaften dieses Nutzers (z. B. einen Führerschein, einen akademischen Grad oder Attribute wie Alter oder Adresse) oder andere Szenarien zu authentifizieren und zu autorisieren, in denen Anmeldedaten ausgestellt und überprüft werden müssen, um die Authentizität einer Entität zu bestätigen.

„Digital Credentials“ ist ein öffentlicher W3C-Standard, der festlegt, wie auf überprüfbare digitale Anmeldedaten eines Nutzers aus einer digitalen Wallet zugegriffen werden kann. Er wird für Web-Anwendungsfälle mit der W3C Credential Management API implementiert. Auf Android-Geräten wird die DigitalCredential API von Credential Manager verwendet, um digitale Anmeldedaten zu überprüfen.

Android-Versionskompatibilität

Die Verifier API wird ab Android 6 (API-Level 23) unterstützt.

Implementierung

So überprüfen Sie digitale Anmeldedaten in Ihrem Android-Projekt:

  1. Fügen Sie dem Build-Skript Ihrer App Abhängigkeiten hinzu und initialisieren Sie eine CredentialManager-Klasse.
  2. Erstellen Sie eine Anfrage für digitale Anmeldedaten und verwenden Sie sie, um eine DigitalCredentialOption zu initialisieren. Erstellen Sie anschließend die GetCredentialRequest.
  3. Starten Sie den getCredential-Ablauf mit der erstellten Anfrage, um eine erfolgreiche GetCredentialResponse zu erhalten oder alle Ausnahmen zu verarbeiten, die auftreten können. Überprüfen Sie nach dem erfolgreichen Abruf die Antwort.

Abhängigkeiten hinzufügen und initialisieren

Fügen Sie dem Gradle-Build-Skript die folgenden Abhängigkeiten hinzu:

dependencies {
    implementation("androidx.credentials:credentials:1.6.0-beta01")
    implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta01")
}

Initialisieren Sie als Nächstes eine Instanz der Klasse CredentialManager.

val credentialManager = CredentialManager.create(context)

Anfrage für digitale Anmeldedaten erstellen

Erstellen Sie eine Anfrage für digitale Anmeldedaten und verwenden Sie sie, um eine DigitalCredentialOption zu initialisieren.

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

Hier ist ein Beispiel für eine OpenId4Vp-Anfrage. Eine vollständige Referenz finden Sie auf dieser Website.

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

Anmeldedaten abrufen

Starten Sie den getCredential-Ablauf mit der erstellten Anfrage. Sie erhalten entweder eine erfolgreiche GetCredentialResponse oder eine GetCredentialException, wenn die Anfrage fehlschlägt.

Der getCredential-Ablauf löst Android-Systemdialogfelder aus, um die verfügbaren Anmeldeoptionen des Nutzers zu präsentieren und die Auswahl zu erfassen. Als Nächstes werden in der Wallet-App, die die ausgewählte Anmeldeoption enthält, Benutzeroberflächen angezeigt, um die Einwilligung einzuholen und Aktionen auszuführen, die zum Generieren einer Antwort für digitale Anmeldedaten erforderlich sind.

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}")
    }
}