Z tego przewodnika dowiesz się, jak używać interfejsu DigitalCredential API do uzyskiwania zweryfikowanych numerów telefonów użytkowników. Proces składa się z 2 etapów:
- Wstępne sprawdzenie: sprawdź, czy operator użytkownika obsługuje ten interfejs API, wysyłając zapytanie do interfejsu Android Telephony API. Jeśli operator nie jest obsługiwany, wróć do normalnego procesu SMS.
- Żądanie
TS.43 token: aplikacja kliencka („weryfikator”) żąda tymczasowego tokena TS.43 z urządzenia użytkownika.TS.43 tokento dane logowania wydane przez operatora, które reprezentują tożsamość użytkownika. - Wymiana tokena na numer telefonu: backend aplikacji wymienia
TS.43 tokenz agregatorem lub operatorem na zweryfikowany numer telefonu użytkownika.
Zgodność z wersją Androida
Interfejs API weryfikacji numeru telefonu jest obsługiwany na Androidzie 10 (poziom API 29) i nowszych wersjach.
Wymagania wstępne
Aby wdrożyć weryfikację numeru telefonu za pomocą interfejsu DigitalCredential API, musisz mieć konto u agregatora lub operatora komórkowego. Agregator współpracuje z operatorami i udostępnia niezbędny interfejs API dla aplikacji, zwykle jako płatny punkt końcowy interfejsu API w chmurze. W tym przewodniku zarówno agregatorzy, jak i operatorzy są określani zbiorczo jako agregatorzy.
Do skryptu kompilacji Gradle musisz też dodać te zależności:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.7.0-alpha02") implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.7.0-alpha02" implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02" }
Implementacja
Zanim wywołasz interfejs Digital Credentials API, sprawdź, czy operator użytkownika obsługuje tę funkcję, używając interfejsu Android Telephony API.
Dodaj uprawnienie READ_PHONE_STATE do pliku AndroidManifest.xml.
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val carrierId = telephonyManager.getSimCarrierId()
Za pomocą tego identyfikatora sprawdź obsługę TS.43 w backendzie agregatora. Jeśli operator tego użytkownika nie jest obsługiwany, możesz skorzystać z metody alternatywnej, np. SMS-a, ponieważ wywołanie interfejsu Digital Credentials API zwraca pusty wynik. W przeciwnym razie kontynuuj proces związany z dokumentami cyfrowymi.
Cały proces przebiega zwykle w ten sposób:
- Poproś agregator o parametry DCQL (Digital Credential Query Language): wywołaj co najmniej 1 agregator i poproś o zestaw parametrów DCQL. DCQL umożliwia określenie dokładnych cyfrowych dokumentów tożsamości, których potrzebujesz od każdego agregatora.
Utwórz żądanie OpenID4VP: w backendzie aplikacji utwórz żądanie OpenID4VP, uwzględniając parametry DCQL z agregatora. Następnie wyślij żądanie OpenID4VP do aplikacji klienckiej.
Wywołaj interfejs Credential Manager API: w aplikacji klienckiej użyj interfejsu Credential Manager API, aby wysłać żądanie OpenID4VP do systemu operacyjnego. W odpowiedzi otrzymasz obiekt odpowiedzi OpenID4VP zawierający
TS.43 Digital Credential. Te dane logowania są zaszyfrowane i mogą zostać odszyfrowane tylko przez powiązanego agregatora. Po otrzymaniu tokena operatora wyślij odpowiedź z aplikacji klienckiej do backendu aplikacji.Sprawdź odpowiedź: w backendzie aplikacji sprawdź odpowiedź OpenID4VP.
Wymiana na numer telefonu: z backendu aplikacji wyślij
TS.43 Digital Credentialdo agregatora. Agregator sprawdza dane uwierzytelniające i zwraca zweryfikowany numer telefonu.
Żądanie parametrów DCQL od agregatora
Z poziomu backendu aplikacji wyślij do agregatora prośbę o obiekt danych uwierzytelniających Digital Credential Query Language (DCQL). Pamiętaj, aby w żądaniu podać liczbę jednorazową i identyfikator żądania. Agregator zwraca obiekt danych logowania DCQL, który ma strukturę podobną do tej:
{
// 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"]
}
]
}
Tworzenie żądania OpenID4VP
Najpierw w backendzie aplikacji utwórz obiekt dcql_query, umieszczając obiekt danych logowania DCQL w tablicy credentials zagnieżdżonej w obiekcie dcql_query, jak w tym przykładzie:
"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"]
}
]
]
}
Następnie utwórz żądanie OpenID4VP o następującej strukturze:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
protocol: w przypadku próśb o weryfikację numeru telefonu musi być ustawiony naopenid4vp-v1-unsigned.response_typeiresponse_mode: stałe oznaczające format żądania o stałych wartościach, odpowiedniovp_tokenidc_api.nonce: unikalna wartość generowana przez backend dla każdego żądania. Liczba jednorazowa w obiekcie danych uwierzytelniających DCQL agregatora musi być zgodna z tą liczbą jednorazową.dcql_query: w tym przypadku użyjdcql_query, aby określić, że żądany jestTS.43 Digital Credential. Możesz też poprosić o inne cyfrowe dokumenty tożsamości.
Następnie umieść żądanie OpenID4VP w obiekcie żądania interfejsu DigitalCredential API i wyślij je do aplikacji klienckiej.
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
Poniższy fragment kodu pokazuje, jak wygenerować żądanie do interfejsu 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
Wywoływanie interfejsu Credential Manager API
W aplikacji klienckiej wywołaj interfejs Credential Manager API, podając żądanie do interfejsu DigitalCredential API dostarczone przez backend aplikacji.
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)
}
}
Odpowiedź interfejsu DigitalCredential API zawiera odpowiedź OpenID4VP. Typowy plik JSON z danymi logowania z wyniku DigitalCredential wygląda tak:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
Z aplikacji klienckiej wyślij odpowiedź interfejsu API DigitalCredential z powrotem do serwera backendu, gdzie można ją zweryfikować i użyć do wymiany na zweryfikowany numer telefonu z agregatorem.
W niektórych przypadkach odpowiedź może zawierać błąd TS.43. Odpowiedź z błędem to obiekt JSON zgodny z formatem odpowiedzi z błędem OpenID4VP:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"error": "<error_code>",
"error_description": "<Human-readable description of the error>",
}
}
Dostępne są 2 możliwe wartości error_code:
invalid_request: wskazuje, że żądanie było nieprawidłowo sformułowane.server_error: wskazuje, że podczas przetwarzania żądania wystąpiły błędy. Może to być błąd lokalny lub problem TS.43.
Pole error_description zawiera dodatkowe informacje o problemie.
Weryfikowanie odpowiedzi dotyczącej cyfrowego dokumentu tożsamości
Poniżej znajdziesz przykład, jak przeanalizować odpowiedź i wykonać krok weryfikacji w backendzie aplikacji:
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.
Wymiana na numer telefonu
Z backendu aplikacji wyślij zweryfikowany TS.43 Digital Credential do punktu końcowego agregatora, aby zweryfikować dane logowania i otrzymać zweryfikowany numer telefonu.
def processDigitalCredentialsResponse(response):
# ... prior steps
# Step 3: Call aggregator endpoint to exchange the verified phone number
callAggregatorPnvEndpoint(ts43_digital_credential)