Ce guide explique comment utiliser l'API DigitalCredential pour obtenir des numéros de téléphone validés pour vos utilisateurs. Le processus se déroule en deux étapes :
- Vérification préalable : vérifiez si l'opérateur de l'utilisateur est compatible avec cette API en interrogeant l'API Android Telephony. Si l'opérateur n'est pas compatible, revenez à votre flux de SMS normal.
- Demander un
TS.43 token: votre application cliente (le "vérificateur") demande un jeton TS.43 temporaire à l'appareil de l'utilisateur. LeTS.43 tokenest un identifiant émis par l'opérateur qui représente l'identité de l'utilisateur. - Échangez le jeton contre un numéro de téléphone : le backend de votre application échange le
TS.43 tokenavec un agrégateur ou un opérateur pour obtenir le numéro de téléphone validé de l'utilisateur.
Compatibilité avec les versions d'Android
L'API de vérification du numéro de téléphone est compatible avec Android 10 (niveau d'API 29) et versions ultérieures.
Prérequis
Pour implémenter la validation du numéro de téléphone avec l'API Digital Credentials, vous devez disposer d'un compte auprès d'un agrégateur ou d'un opérateur mobile. Un agrégateur interagit avec les opérateurs et fournit la surface d'API nécessaire à votre application, généralement en tant que point de terminaison d'API cloud facturable. Dans ce guide, les agrégateurs et les opérateurs sont collectivement appelés agrégateurs.
Vous devez également ajouter les dépendances suivantes à votre script de compilation Gradle :
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" }
Implémentation
Avant d'appeler l'API Digital Credentials, vérifiez si l'opérateur de l'utilisateur est compatible avec cette fonctionnalité à l'aide de l'API Android Telephony.
Ajoutez l'autorisation READ_PHONE_STATE à votre fichier AndroidManifest.xml.
val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val carrierId = telephonyManager.getSimCarrierId()
Avec cet ID, vérifiez la compatibilité avec TS.43 auprès de votre backend d'agrégateur. Si l'opérateur de cet utilisateur n'est pas compatible, vous pouvez utiliser une autre méthode, comme les SMS, car l'appel de l'API Digital Credentials renvoie un résultat vide. Sinon, poursuivez avec le flux Digital Credentials.
Le processus de bout en bout suit généralement ces étapes :
- Demander des paramètres DCQL (Digital Credential Query Language) à un agrégateur : appelez un ou plusieurs agrégateurs et demandez un ensemble de paramètres DCQL. Le DCQL vous permet de spécifier les identifiants numériques exacts dont vous avez besoin pour chaque agrégateur.
Créer la requête OpenID4VP : à partir du backend de votre application, créez la requête OpenID4VP, en incluant les paramètres DCQL de l'agrégateur. Ensuite, envoyez la requête OpenID4VP à votre application cliente.
Appeler l'API Credential Manager : dans votre application cliente, utilisez l'API Credential Manager pour envoyer la requête OpenID4VP au système d'exploitation. En réponse, vous recevez un objet de réponse OpenID4VP contenant le
TS.43 Digital Credential. Cet identifiant est chiffré et ne peut être déchiffré que par l'agrégateur associé. Après avoir reçu le jeton de l'opérateur, envoyez la réponse de votre application cliente au backend de l'application.Valider la réponse : dans le backend de votre application, validez la réponse OpenID4VP.
Échange contre un numéro de téléphone : depuis le backend de votre application, envoyez le
TS.43 Digital Credentialà l'agrégateur. L'agrégateur valide les identifiants et renvoie le numéro de téléphone validé.
Demander des paramètres DCQL à un agrégateur
Depuis le backend de votre application, envoyez une requête à l'agrégateur pour obtenir un objet d'identifiant DCQL (Digital Credential Query Language). Veillez à fournir un nonce et un ID de requête dans votre requête. L'agrégateur renvoie l'objet d'identifiant DCQL, qui présente une structure semblable à celle-ci :
{
// 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"]
}
]
}
Créer la requête OpenID4VP
Tout d'abord, à partir du backend de votre application, créez un objet dcql_query en plaçant l'objet d'identifiant DCQL dans un tableau credentials imbriqué dans un objet dcql_query, comme illustré dans l'exemple suivant :
"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"]
}
]
]
}
Ensuite, créez une requête OpenID4VP avec la structure suivante :
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
protocol: doit être défini suropenid4vp-v1-unsignedpour les demandes de validation de numéro de téléphone.response_typeetresponse_mode: constantes indiquant le format de la requête avec les valeurs fixesvp_tokenetdc_api, respectivement.nonce: valeur unique générée par votre backend pour chaque requête. Le nonce de l'objet d'identifiant DCQL de l'agrégateur doit correspondre à ce nonce.dcql_query: dans ce cas, utilisezdcql_querypour spécifier qu'unTS.43 Digital Credentialest demandé. Vous pouvez également demander d'autres identifiants numériques ici.
Ensuite, encapsulez la requête OpenID4VP dans un objet de requête API DigitalCredential et envoyez-la à l'application cliente.
{
"requests":
[
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"response_type": "vp_token",
"response_mode": "dc_api",
"nonce": "...",
"dcql_query": { ... }
}
}
]
}
L'extrait de code suivant montre comment générer la requête 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
Appeler l'API Credential Manager
Dans votre application cliente, appelez l'API Credential Manager avec la requête API DigitalCredential fournie par le backend de votre application.
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 réponse de l'API DigitalCredential contient la réponse OpenID4VP. Voici un exemple de fichier JSON d'identifiants issu du résultat DigitalCredential :
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"vp_token": {
"aggregator1": ["eyJhbGciOiAiRVMy..."] # The encrypted TS.43 Digital
# Credential in an array structure.
}
}
}
Depuis votre application cliente, renvoyez la réponse de l'API DigitalCredential au serveur backend, où elle peut être validée et utilisée pour l'échange contre le numéro de téléphone validé avec un agrégateur.
Dans certains cas, la réponse peut contenir une erreur TS.43. La réponse d'erreur est un objet JSON au format de réponse d'erreur OpenID4VP :
{
"protocol": "openid4vp-v1-unsigned",
"data": {
"error": "<error_code>",
"error_description": "<Human-readable description of the error>",
}
}
Il existe deux valeurs error_code possibles :
invalid_request: indique que la requête est incorrecte.server_error: indique que des échecs se sont produits lors du traitement de la requête. Il peut s'agir d'erreurs locales ou de problèmes TS.43.
Le champ error_description fournit des détails supplémentaires sur le problème.
Valider la réponse Digital Credential
Voici un exemple d'analyse de la réponse et d'exécution de l'étape de validation dans le backend de votre application :
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.
Échanger contre un numéro de téléphone
Depuis le backend de votre application, envoyez le TS.43 Digital Credential validé au point de terminaison de l'agrégateur pour valider les identifiants et recevoir le numéro de téléphone validé.
def processDigitalCredentialsResponse(response):
# ... prior steps
# Step 3: Call aggregator endpoint to exchange the verified phone number
callAggregatorPnvEndpoint(ts43_digital_credential)