במדריך הזה מוסבר איך להשתמש ב-DigitalCredential API כדי לקבל מספרי טלפון מאומתים של המשתמשים. התהליך כולל שני שלבים:
- בקשת
TS.43 token
: אפליקציית הלקוח (המאמתת) מבקשת טוקן זמני של TS.43 מהמכשיר של המשתמש.TS.43 token
הוא פרט כניסה שהונפק על ידי הספק ומייצג את הזהות של המשתמש. - החלפת הטוקן במספר טלפון: הקצה האחורי של האפליקציה מחליף את הטוקן
TS.43 token
עם צד שלישי או עם ספק סלולר כדי לקבל את מספר הטלפון המאומת של המשתמש.
דרישות מוקדמות
כדי להטמיע אימות של מספר טלפון באמצעות DigitalCredential API, אתם צריכים חשבון אצל צד שלישי שמספק שירותי אימות. מצטבר מבצע אינטראקציה עם ספקים ומספק את ממשק ה-API הדרוש לאפליקציה שלכם, בדרך כלל כנקודת קצה של API בענן שניתן לחיוב.
צריך גם להוסיף את יחסי התלות הבאים לסקריפט של Gradle:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-alpha05") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-alpha05") }
מגניב
dependencies { implementation "androidx.credentials:credentials:1.6.0-alpha05" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-alpha05" }
הטמעה
בדרך כלל התהליך מקצה לקצה כולל את השלבים הבאים:
- בקשת פרמטרים של DCQL (שפת שאילתות של אישורים דיגיטליים) מאגרגטור: מתקשרים לאגרגטור אחד או יותר ומבקשים קבוצה של פרמטרים של DCQL. בעזרת DCQL אפשר לציין את פרטי הכניסה הדיגיטליים המדויקים שאתם צריכים מכל צובר.
יצירת בקשת OpenID4VP: בבק-אנד של האפליקציה, יוצרים את בקשת OpenID4VP, וכוללים בה את פרמטר ה-DCQL מהאגרגטור. לאחר מכן, שולחים את בקשת OpenID4VP לאפליקציית הלקוח.
הפעלת Credential Manager API: באפליקציית הלקוח, משתמשים ב-Credential Manager API כדי לשלוח את בקשת OpenID4VP למערכת ההפעלה. בתגובה, מקבלים אובייקט תגובה של OpenID4VP שמכיל את
TS.43 Digital Credential
. פרטי הכניסה האלה מוצפנים, ורק המצטבר המשויך יכול לפענח אותם. אחרי שמקבלים את האסימון של חברת התובלה, שולחים את התגובה מאפליקציית הלקוח אל ה-Backend של האפליקציה.אימות התשובה: בקצה העורפי של האפליקציה, מאמתים את התשובה של OpenID4VP.
Exchange for phone number: מחלק האחורי של האפליקציה, שולחים את
TS.43 Digital Credential
אל האגרגטור. הספק המצטבר מאמת את פרטי הכניסה ומחזיר את מספר הטלפון המאומת.
בקשת פרמטרים של DCQL מאגרגטור
משרת הקצה העורפי של האפליקציה, שולחים בקשה למצטבר לאובייקט של פרטי כניסה בשפת שאילתות של פרטי כניסה דיגיטליים (DCQL). חשוב לספק בבקשה ערך חד-פעמי ומזהה בקשה. האגרגטור מחזיר את אובייקט פרטי הכניסה של DCQL, עם מבנה שדומה לזה:
{
// The credential ID is mapped to the request ID that is sent in your request to the aggregator.
"id": "aggregator1",
"format": "dc-authorization+sd-jwt",
"meta": {
"vct_values": [
"number-verification/device-phone-number/ts43"
],
"credential_authorization_jwt": "..."
},
"claims": [
{
"path": ["subscription_hint"],
"values": [1]
},
{
"path": ["phone_number_hint"],
"values": ["+14155552671"]
}
]
}
יצירת בקשת OpenID4VP
קודם כל, בשרת העורפי של האפליקציה, יוצרים אובייקט dcql_query
על ידי הצבת אובייקט האישורים של DCQL במערך credentials
שמוטמע באובייקט dcql_query
, כמו בדוגמה הבאה:
"dcql_query": {
"credentials": [
"id": "aggregator1",
"format": "dc-authorization+sd-jwt",
"meta": {
"vct_values": [
"number-verification/device-phone-number/ts43"
],
"credential_authorization_jwt": "..."
},
"claims": [
{
"path": ["subscription_hint"],
"values": [1]
},
{
"path": ["phone_number_hint"],
"values": ["+14155552671"]
}
]
]
}
לאחר מכן, יוצרים בקשת OpenID4VP במבנה הבא:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
-
protocol
: צריך להגדיר את הערךopenid4vp-v1-unsigned
לבקשות לאימות מספר טלפון. -
response_type
ו-response_mode
: קבועים שמציינים את הפורמט של הבקשה עם הערכים הקבועיםvp_token
ו-dc_api
, בהתאמה. -
nonce
: ערך ייחודי שנוצר על ידי ה-Backend לכל בקשה. ה-nonce באובייקט של פרטי הכניסה של המצטבר ב-DCQL צריך להיות זהה ל-nonce הזה. -
dcql_query
: במקרה הזה, משתמשים ב-dcql_query
כדי לציין שמבוקשTS.43 Digital Credential
. אפשר גם לבקש כאן פרטי כניסה דיגיטליים אחרים.
לאחר מכן, עוטפים את בקשת OpenID4VP באובייקט בקשה של DigitalCredential API ושולחים אותו לאפליקציית הלקוח.
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
בקטע הקוד הבא מוצג איך ליצור בקשה ל-DigitalCredential API:
def GenerateDCRequest():
credentials = []
aggregator1_dcql = call_aggregator_endpoint(nonce, "aggregator1", additional_params)
credentials.append(aggregator1_dcql) # You can optionally work with multiple
# aggregators, or request other types of credentials
val dc_request =
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": {"credentials": credentials}
}
}
]
}
return dc_request
שליחת קריאה ל-Credential Manager API
באפליקציית הלקוח, מבצעים קריאה ל-Credential Manager API, עם בקשת DigitalCredential API שסופקה על ידי הקצה העורפי של האפליקציה.
val requestJson = generateTs43DigitalCredentialRequestFromServer()
val digiCredOption = GetDigitalCredentialOption(requestJson = requestJson)
val getCredRequest = GetCredentialRequest(
listOf(digiCredOption)
)
coroutineScope.launch {
try {
val response = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
val credential = response.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}")
}
}
} catch (e : GetCredentialException) {
// If user cancels the operation, the feature isn't available, or the
// SIM doesn't support the feature, a GetCredentialCancellationException
// will be returned. Otherwise, a GetCredentialUnsupportedException will
// be returned with details in the exception message.
handleFailure(e)
}
}
התגובה של DigitalCredential API מכילה את התגובה של OpenID4VP. דוגמה ל-JSON של פרטי כניסה מתוצאת DigitalCredential
:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
מהאפליקציה של הלקוח, שולחים את התגובה של DigitalCredential API בחזרה לשרת הקצה העורפי, שם אפשר לאמת אותה ולהשתמש בה כדי להחליף את מספר הטלפון המאומת עם צד שלישי.
אימות התשובה של תעודת ההסמכה הדיגיטלית
הדוגמה הבאה מראה איך לנתח את התגובה ולבצע את שלב האימות בבק-אנד של האפליקציה:
def processDigitalCredentialsResponse(response):
# Step 1: Parse out the TS.43 Digital Credential from the response
openId4VpResponse = response['data']
ts43_digital_credential = response['vp_token']["aggregator1"][0]
# Step 2: Perform response validation
verifyResponse(ts43_digital_credential)
def verifyResponse(ts43_digital_credential):
# The returned ts43_digital_credential is an SD-JWT-based Verifiable Credentials
# (SD-JWT VC) as defined in this IETF spec. The section 3.4 of the specification
# outlines how to validate the credential. At a high level, the steps involves
# validating (1) the nonce in the response credential matches the one in the
# request, (2) the integrity of the credential by checking the credential is
# signed by the trusted issuer Android Telephony, and (3) other validity
# properties associated with this credential, such as issue time and expiration
# time
# In most cases, you can use an SD-JWT VC library to perform these validations.
# Some aggregators may also perform the validation logic for you. Check with your
# aggregator to decide the exact scope of the validation required.
החלפה של מספר טלפון
משרת הקצה של האפליקציה, שולחים את TS.43 Digital Credential
המאומת לנקודת הקצה של האגרגטור כדי לאמת את פרטי הכניסה ולקבל את מספר הטלפון המאומת.
def processDigitalCredentialsResponse(response):
# ... prior steps
# Step 3: Call aggregator endpoint to exchange the verified phone number
callAggregatorPnvEndpoint(ts43_digital_credential)