Weryfikacja cyfrowych dokumentów tożsamości w aplikacjach na Androida może służyć do uwierzytelniania i autoryzowania tożsamości użytkownika (np. dowodu tożsamości wydanego przez organ państwowy), informacji o tym użytkowniku (np. prawa jazdy, dyplomu ukończenia studiów lub atrybutów takich jak wiek czy adres) lub w innych sytuacjach, w których dokument tożsamości musi zostać wydany i zweryfikowany w celu potwierdzenia autentyczności podmiotu.
Cyfrowe dokumenty tożsamości to publiczny standard W3C, który określa, jak uzyskiwać dostęp do weryfikowalnych cyfrowych dokumentów tożsamości użytkownika z cyfrowego portfela. Jest on wdrażany w przypadku zastosowań internetowych za pomocą interfejsu W3C Credential Management API. Na Androidzie do weryfikacji cyfrowych danych logowania używany jest interfejs DigitalCredential Credential Manager.
Implementacja
Aby zweryfikować cyfrowe dokumenty tożsamości w projekcie na Androida:
- Dodaj zależności do skryptu kompilacji aplikacji i zainicjuj klasę
CredentialManager. - Utwórz żądanie cyfrowych danych logowania i użyj go do zainicjowania
DigitalCredentialOption, a następnie utwórzGetCredentialRequest. - Uruchom przepływ
getCredentialza pomocą utworzonego żądania, aby otrzymać odpowiedźGetCredentialResponselub obsłużyć wszelkie wyjątki, które mogą wystąpić. Po pobraniu odpowiedzi sprawdź ją.
Dodawanie zależności i inicjowanie
Dodaj do skryptu kompilacji Gradle te zależności:
dependencies {
implementation("androidx.credentials:credentials:1.6.0-beta01")
implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta01")
}
Następnie zainicjuj instancję klasy CredentialManager.
val credentialManager = CredentialManager.create(context)
Tworzenie prośby o dane logowania
Utwórz żądanie cyfrowych poświadczeń i użyj go do zainicjowania 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)
)
Oto przykład żądania OpenId4Vp. Pełne informacje znajdziesz na tej stronie.
{
"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"
]
}
]
}
]
}
}
}
]
}
Uzyskiwanie danych logowania
Uruchom proces getCredential za pomocą utworzonego żądania. Otrzymasz GetCredentialResponse, jeśli żądanie się powiedzie, lub GetCredentialException, jeśli się nie powiedzie.
Proces getCredential wywołuje okna systemowe Androida, aby wyświetlić użytkownikowi dostępne opcje danych logowania i zebrać jego wybór. Następnie aplikacja portfela zawierająca wybraną opcję danych logowania wyświetli interfejsy, które umożliwią uzyskanie zgody i wykonanie działań niezbędnych do wygenerowania odpowiedzi dotyczącej cyfrowych danych logowania.
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}")
}
}