En esta guía, se detalla cómo usar la API de DigitalCredential para obtener números de teléfono verificados de tus usuarios. El proceso consta de dos pasos:
- Solicita un
TS.43 token
: Tu app cliente (el "verificador") solicita un token TS.43 temporal desde el dispositivo del usuario. ElTS.43 token
es una credencial emitida por el operador que representa la identidad del usuario. - Intercambia el token por un número de teléfono: El backend de tu app intercambia el
TS.43 token
con un agregador o un operador para obtener el número de teléfono verificado del usuario.
Requisitos previos
Para implementar la verificación del número de teléfono con la API de DigitalCredential, necesitas una cuenta con un agregador. Un agregador interactúa con los operadores y proporciona la superficie de API necesaria para tu app, por lo general, como un extremo de API de Cloud facturable.
También debes agregar las siguientes dependencias a tu secuencia de comandos de compilación de Gradle:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-alpha05") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-alpha05") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.6.0-alpha05" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-alpha05" }
Implementación
Por lo general, el proceso integral sigue estos pasos:
- Solicita parámetros de DCQL (lenguaje de consulta de credenciales digitales) a un agregador: Llama a uno o más agregadores y solicita un conjunto de parámetros de DCQL. DCQL te permite especificar las credenciales digitales exactas que necesitas de cada agregador.
Crea la solicitud de OpenID4VP: Desde el backend de tu app, crea la solicitud de OpenID4VP y, al mismo tiempo, incluye los parámetros de DCQL del agregador. Luego, envía la solicitud de OpenID4VP a tu app cliente.
Llama a la API de Credential Manager: En tu app cliente, usa la API de Credential Manager para enviar la solicitud de OpenID4VP al sistema operativo. En respuesta, recibirás un objeto de respuesta OpenID4VP que contiene el
TS.43 Digital Credential
. Esta credencial está encriptada y solo el agregador asociado puede desencriptarla. Después de recibir el token de la empresa de transporte, envía la respuesta de tu app cliente al backend de la app.Valida la respuesta: En el backend de tu app, valida la respuesta de OpenID4VP.
Intercambio por número de teléfono: Desde el backend de tu app, envía el
TS.43 Digital Credential
al agregador. El agregador valida la credencial y devuelve el número de teléfono verificado.
Solicita parámetros de DCQL a un agregador
Desde el backend de tu app, envía una solicitud al agregador para obtener un objeto de credencial del lenguaje de consultas de credenciales digitales (DCQL). Asegúrate de proporcionar un nonce y un ID de solicitud en tu solicitud. El agregador devuelve el objeto de credencial de DCQL, que tiene una estructura similar a la siguiente:
{
// 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"]
}
]
}
Crea la solicitud de OpenID4VP
Primero, desde el backend de tu app, crea un objeto dcql_query
colocando el objeto de credenciales de DCQL en un array credentials
anidado dentro de un objeto dcql_query
, como se muestra en el siguiente ejemplo:
"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"]
}
]
]
}
Luego, crea una solicitud de OpenID4VP con la siguiente estructura:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
protocol
: Debe establecerse enopenid4vp-v1-unsigned
para las solicitudes de verificación de números de teléfono.response_type
yresponse_mode
: Son constantes que denotan el formato de la solicitud con valores fijosvp_token
ydc_api
, respectivamente.nonce
: Es un valor único que genera tu backend para cada solicitud. El valor de nonce en el objeto de credencial de DCQL del agregador debe coincidir con este valor de nonce.dcql_query
: En este caso, usadcql_query
para especificar que se solicita unTS.43 Digital Credential
. También puedes solicitar otras credenciales digitales aquí.
Luego, encapsula la solicitud de OpenID4VP en un objeto de solicitud de la API de DigitalCredential y envíalo a la app cliente.
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
En el siguiente fragmento, se muestra cómo generar la solicitud de la API de DigitalCredential:
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
Llama a la API de Credential Manager
En tu app cliente, llama a la API de Credential Manager con la solicitud de la API de DigitalCredential que proporciona el backend de tu app.
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)
}
}
La respuesta de la API de DigitalCredential contiene la respuesta de OpenID4VP. Un archivo JSON de credenciales típico del resultado de DigitalCredential
es el siguiente:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
Desde tu app cliente, envía la respuesta de la API de DigitalCredential al servidor de backend, donde se puede validar y usar para intercambiar el número de teléfono verificado con un agregador.
Valida la respuesta de la credencial digital
A continuación, se muestra un ejemplo de cómo analizar la respuesta y realizar el paso de validación en el backend de tu app:
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.
Intercambio por número de teléfono
Desde el backend de tu app, envía el TS.43 Digital Credential
validado al extremo del agregador para validar la credencial y recibir el número de teléfono verificado.
def processDigitalCredentialsResponse(response):
# ... prior steps
# Step 3: Call aggregator endpoint to exchange the verified phone number
callAggregatorPnvEndpoint(ts43_digital_credential)