درستیسنجی اعتبارنامه دیجیتال در برنامههای Android میتواند برای اصالتسنجی و صدور مجوز برای هویت کاربر (مانند مدرک شناسایی دولتی)، ویژگیهای مربوط به آن کاربر (مانند گواهینامه رانندگی، مدرک تحصیلی، یا مشخصههایی مانند سن یا نشانی)، یا سناریوهای دیگری که در آنها لازم است اعتبارنامهای برای اثبات اصالت یک نهاد صادر و درستیسنجی شود استفاده شود.
Verifer API در Android 9 (سطح میانای برنامهسازی کاربردی ۲۸) و بالاتر پشتیبانی میشود.
پیادهسازی
برای درستیسنجی کردن اطلاعات کاربری دیجیتال در پروژه Android، کارهای زیر را انجام دهید:
- وابستگیها را به دستورگان ساخت برنامهتان اضافه کنید و کلاس
CredentialManagerرا مقداردهی اولیه کنید. - درخواست اعتبارنامه دیجیتال بسازید و از آن برای مقداردهی اولیه
DigitalCredentialOptionاستفاده کنید، سپسGetCredentialRequestرا بسازید. - جریان
getCredentialرا با درخواست ساختهشده راهاندازی کنید تاGetCredentialResponseموفقیتآمیز دریافت کنید یا هرگونه استثنایی را که ممکن است رخ دهد مدیریت کنید. پساز بازیابی موفق، پاسخ را اعتبارسنجی کنید.
افزودن وابستگیها و مقداردهی اولیه
وابستگیهای زیر را به دستورگان ساخت 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۱ را نشان میدهد. برای جزئیات بیشتر درباره فیلدهای این درخواست، به اسناد 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"
]
}
]
}
]
}
}
}
]
}
دریافت اطلاعات کاربری
جریان 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.
}
else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
}
}
درخواستهای چنداعتبارنامهای انعطافپذیر
Digital Credentials API همچنین از درخواست چندین نوع اعتبارنامه بهطور همزمان بااستفاده از OpenID4VP پشتیبانی میکند:
- درخواستهای همزمان: درخواست چندین اطلاعات کاربری در یک تراکنش کاربر. برای مثال، یک برنامه سفر میتواند بهطور همزمان کارت پرواز و مدرک شناسایی دولتی را درخواست کند و به کاربر اجازه دهد هر دو را با یک تکضرب بررسی کند و رضایت دهد.
- انجام انعطافپذیر: پذیرفتن هریک از انواع اعتبارنامه یا صادرکنندگان. برای مثال، جریان درستیسنجی سن میتواند گواهینامه رانندگی یا گذرنامه را بپذیرد، و به کاربران امکان دهد درخواست را بااستفاده از هرکدام از این مدارک شناسایی که در نگهدارنده خود ذخیره کردهاند تکمیل کنند.
در اینجا نمونهای از درخواست چند اعتبارنامه در یک درخواست آورده شده است:
{
"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"
]
}
]
}
]
}
مدیریت پاسخ
پساز درخواست اطلاعات کاربری، GetCredentialResponse
برگرداندهشده از 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}")
}
}
}
رسیدگی به موارد استثنا
برنامه شما باید خطاهایی را که ممکن است ایجاد شود مدیریت کند، ازجمله اگر هیچ اطلاعات اعتباری در دستگاه وجود نداشته باشد یا اگر کاربر عملیات را لغو کند:
// 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}")
}
}