אימות של מסמכים דיגיטליים באפליקציות ל-Android יכול לשמש לאימות ולאישור של זהות משתמש (למשל תעודה מזהה רשמית), מאפיינים של המשתמש (למשל רישיון נהיגה, תואר אקדמי או מאפיינים כמו גיל או כתובת) או תרחישים אחרים שבהם צריך להנפיק ולאמת מסמך כדי לאשר את האותנטיות של ישות.
'מסמכים דיגיטליים' הוא תקן ציבורי של W3C שמפרט איך לגשת למסמכים דיגיטליים ניתנים לאימות של משתמשים מתוך ארנק דיגיטלי. התקן מיושם בתרחישי שימוש באינטרנט באמצעות W3C Credential Management API. ב-Android, נעשה שימוש ב-API DigitalCredential של Credential Manager לאימות פרטי כניסה דיגיטליים.
תאימות לגרסת Android
Verifier API נתמך ב-Android 6 (רמת API 23) ומעלה.
הטמעה
כדי לאמת פרטי כניסה דיגיטליים בפרויקט Android, צריך לבצע את הפעולות הבאות:
- מוסיפים תלויות לסקריפט הבנייה של האפליקציה ומפעילים את המחלקה
CredentialManager. - יוצרים בקשה לפרטי כניסה דיגיטליים ומשתמשים בה כדי לאתחל את
DigitalCredentialOption, ואז יוצרים אתGetCredentialRequest. - מפעילים את רצף הפעולות
getCredentialעם הבקשה שנוצרה כדי לקבלGetCredentialResponseאו לטפל בחריגים שעלולים להתרחש. אחרי השליפה, צריך לאמת את התגובה.
הוספת יחסי תלות והפעלה ראשונית
מוסיפים את יחסי התלות הבאים לסקריפט ה-build של Gradle:
dependencies {
implementation("androidx.credentials:credentials:1.6.0-beta01")
implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta01")
}
אחר כך, מאתחלים מופע של המחלקה CredentialManager.
val credentialManager = CredentialManager.create(context)
יצירת בקשה לפרטי כניסה דיגיטליים
יוצרים בקשה לפרטי כניסה דיגיטליים ומשתמשים בה כדי לאתחל 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)
)
זוהי דוגמה לבקשת OpenId4Vp. אפשר למצוא הפניה מלאה באתר הזה.
{
"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"
]
}
]
}
]
}
}
}
]
}
קבלת פרטי הכניסה
מפעילים את התהליך getCredential עם הבקשה שנוצרה. תקבלו GetCredentialResponse אם הבקשה תצליח, או GetCredentialException אם היא תיכשל.
תהליך getCredential מפעיל תיבות דו-שיח של מערכת Android כדי להציג למשתמש את האפשרויות הזמינות של פרטי הכניסה ולאסוף את הבחירה שלו. לאחר מכן, באפליקציית הארנק הדיגיטלי שכוללת את אפשרות האישורים שנבחרה יוצגו ממשקי משתמש לאיסוף הסכמה ולביצוע הפעולות הנדרשות ליצירת תשובה של אישור דיגיטלי.
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}")
}
}