Este guia detalha como usar a API DigitalCredential para receber números de telefone verificados dos seus usuários. O processo envolve duas etapas:
- Solicitar um
TS.43 token: o app cliente (o "verificador") solicita um token temporário TS.43 do dispositivo do usuário. OTS.43 tokené uma credencial emitida pela operadora que representa a identidade do usuário. - Trocar o token por um número de telefone: o back-end do app troca o
TS.43 tokenpor um agregador ou uma operadora para receber o número de telefone verificado do usuário.
Compatibilidade com a versão do Android
A API Phone Number Verification é compatível com o Android 10 (nível 29 da API) e versões mais recentes.
Pré-requisitos
Para implementar a verificação de número de telefone com a API DigitalCredential, você precisa de uma conta com um agregador. Um agregador interage com as operadoras e fornece a superfície de API necessária para seu app, geralmente como um endpoint de API de nuvem faturável.
Você também precisa adicionar as seguintes dependências ao script de build do Gradle:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.7.0-alpha01") implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha01") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.7.0-alpha01" implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha01" }
Implementação
O processo completo geralmente segue estas etapas:
- Solicitar parâmetros de DCQL (Digital Credential Query Language) de um agregador: chame um ou mais agregadores e solicite um conjunto de parâmetros de DCQL parameters. O DCQL permite especificar as credenciais digitais exatas de que você precisa de cada agregador.
Criar a solicitação OpenID4VP: no back-end do app, crie a solicitação OpenID4VP, incluindo os parâmetros de DCQL do agregador. Em seguida, envie a solicitação OpenID4VP para o app cliente.
Chamar a API Credential Manager: no app cliente, use a API Credential Manager para enviar a solicitação OpenID4VP ao sistema operacional. Em resposta, você recebe um objeto de resposta OpenID4VP contendo a
TS.43 Digital Credential. Essa credencial é criptografada e só pode ser descriptografada pelo agregador associado. Depois de receber o token da operadora, envie a resposta do app cliente para o back-end do app.Validar a resposta: no back-end do app, valide a resposta OpenID4VP.
Trocar pelo número de telefone: no back-end do app, envie o
TS.43 Digital Credentialpara o agregador. O agregador valida a credencial e retorna o número de telefone verificado.
Solicitar parâmetros de DCQL de um agregador
No back-end do app, envie uma solicitação ao agregador para um objeto de credencial da linguagem de consulta de credenciais digitais (DCQL, na sigla em inglês). Forneça um valor de uso único e um ID de solicitação. O agregador retorna o objeto de credencial DCQL, que tem uma estrutura semelhante a esta:
{
// 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"]
}
]
}
Criar a solicitação OpenID4VP
Primeiro, no back-end do app, crie um objeto dcql_query colocando o objeto de credencial DCQL em uma matriz credentials aninhada em um objeto dcql_query, conforme mostrado no exemplo a seguir:
"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"]
}
]
]
}
Em seguida, crie uma solicitação OpenID4VP com a seguinte estrutura:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
protocol: precisa ser definido comoopenid4vp-v1-unsignedpara solicitações de verificação de número de telefone.response_typeeresponse_mode: constantes que denotam o formato da solicitação com valores fixosvp_tokenedc_api, respectivamente.nonce: um valor exclusivo gerado pelo back-end para cada solicitação. O valor de uso único no objeto de credencial DCQL do agregador precisa corresponder a esse valor.dcql_query: nesse caso, usedcql_querypara especificar que umaTS.43 Digital Credentialestá sendo solicitada. Você também pode solicitar outras credenciais digitais aqui.
Em seguida, encapsule a solicitação OpenID4VP em um objeto de solicitação de API DigitalCredential e envie-o para o app cliente.
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
O snippet a seguir demonstra como gerar a solicitação da API 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
Chamar a API Credential Manager
No app cliente, faça uma chamada para a API Credential Manager, com a solicitação de API DigitalCredential fornecida pelo back-end do 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)
}
}
A resposta da API DigitalCredential contém a resposta OpenID4VP. Um json de credencial típico do resultado DigitalCredential é o seguinte:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
No app cliente, envie a resposta da API DigitalCredential de volta ao servidor de back-end, onde ela pode ser validada e usada para trocar o número de telefone verificado com um agregador.
Em alguns casos, a resposta pode conter um erro TS.43. A resposta de erro é um objeto json que segue o formato de resposta de erro OpenID4VP:
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"error": "<error_code>",
"error_description": "<Human-readable description of the error>",
}
}
Há dois valores possíveis de error_code:
invalid_request: indica que a solicitação estava malformada.server_error: indica que houve falhas ao processar a solicitação. Isso pode ser erros locais ou problemas de TS.43.
O campo error_description fornece mais detalhes sobre o problema.
Validar a resposta da credencial digital
Confira a seguir um exemplo de como analisar a resposta e executar a etapa de validação no back-end do 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.
Trocar pelo número de telefone
No back-end do app, envie a TS.43 Digital Credential validada para o endpoint do agregador, para validar a credencial e receber o número de telefone verificado.
def processDigitalCredentialsResponse(response):
# ... prior steps
# Step 3: Call aggregator endpoint to exchange the verified phone number
callAggregatorPnvEndpoint(ts43_digital_credential)