Se pueden aceptar IDs digitales en los flujos en la aplicación y web. Para aceptar credenciales de la Billetera de Google, deberás hacer lo siguiente:
- Realiza la integración con la app o la Web siguiendo las instrucciones proporcionadas.
- Usa el ID de prueba para probar tu flujo en la zona de pruebas de la Billetera de Google.
- Cuando esté todo listo para lanzar la función, completa este formulario para solicitar y aceptar las condiciones del servicio para aceptar credenciales de la Billetera de Google.
Requisitos previos
Para probar la presentación de IDs de forma digital, primero debes inscribirte en el programa de versión beta pública con la cuenta de prueba prevista (debe ser una cuenta de Gmail). Luego, proporciona los siguientes detalles a tu contacto de Google designado.
- Vínculo a las Condiciones del Servicio
- Logotipo
- Sitio web
- IDs de paquetes de aplicaciones (para integraciones de apps para Android)
- Incluye compilaciones de desarrollo y depuración
- Firma de la app
$ $ANDROID_SDK/build-tools/$BUILD_TOOLS_VERSION/apksigner verify --print-certs -v $APK
- ID de Gmail que se usó para unirse a la versión beta pública
Formatos de credenciales admitidos
Existen varios estándares propuestos que definen el formato de datos de los documentos de identidad digital, y dos de ellos han ganado una gran aceptación en la industria:
- mdocs: Se define según la norma ISO.
- Credenciales verificables de W3C: Definidas por W3C.
Si bien el Administrador de credenciales de Android admite ambos formatos, por el momento, la Billetera de Google solo admite los documentos de identidad digitales basados en mdoc.
Credenciales admitidas
Google Wallet admite 2 tipos de credenciales:
- Licencia de conducir digital (mDL)
- Pase de ID
Puedes solicitar cualquiera de las credenciales en tu flujo con un solo cambio de parámetro.
Experiencia del usuario
En esta sección, se describe el flujo recomendado para las presentaciones en línea. El flujo muestra la presentación de la edad a una app para la entrega de bebidas alcohólicas, pero la UX es similar para la Web y otros tipos de presentaciones.
![]() |
![]() |
![]() |
![]() |
![]() |
Se le solicita al usuario que verifique su edad en la app o el sitio web | El usuario ve las credenciales aptas disponibles | El usuario ve la página de confirmación en la Billetera de Google | El usuario se autentica para confirmar el uso compartido | Datos enviados a la app o al sitio web |
Notas clave
- La app o el sitio web tienen flexibilidad para crear el punto de entrada a la API. Como se muestra en el paso 1, recomendamos mostrar un botón genérico, como "Verificar con documento de identidad digital", ya que, con el tiempo, esperamos que haya opciones más allá de la Billetera de Google disponibles a través de la API.
- Android renderiza la pantalla del selector en el paso 2. Las credenciales aptas se determinan a partir de una coincidencia entre la lógica de registro proporcionada por cada billetera y la solicitud enviada por la parte que confía.
- El paso 3 lo renderiza la Billetera de Google. En esta pantalla, la Billetera de Google mostrará el nombre, el logotipo y la política de privacidad que proporcione el desarrollador.
Agrega un flujo de ID digital
En el caso de que el usuario no tenga una credencial, recomendamos proporcionar un vínculo junto al botón "Verificar con documento de identidad digital" que lo dirija a la Billetera de Google para que pueda agregar un documento de identidad digital.
![]() |
![]() |
Se le solicita al usuario que verifique su edad en la app o el sitio web | Se dirige al usuario a la Billetera de Google para obtener un documento de identidad digital |
No hay un ID digital disponible
Si el usuario selecciona la opción "Verificar con ID digital" sin tener un ID digital, se le mostrará este mensaje de error.
![]() |
![]() |
Se le solicita al usuario que verifique su edad en la app o el sitio web | Se muestra un error al usuario si no tiene un documento de identidad digital |
La API no admite una función para saber de forma silenciosa si el usuario tiene alguna identificación digital disponible para preservar su privacidad. Por lo tanto, te recomendamos que incluyas la opción de vínculo de incorporación como se muestra.
Formato de solicitud para solicitar credenciales de ID desde la billetera
A continuación, se muestra un ejemplo de una solicitud de mdoc requestJson
para obtener credenciales de identidad de cualquier billetera en un dispositivo Android o en la Web.
{
"requests" : [
{
"protocol": "openid4vp",
"data": {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
Solicitar encriptación
El objeto client_metadata
contiene la clave pública de encriptación para cada solicitud. Deberás almacenar claves privadas para cada solicitud y usarlas para autenticar y autorizar el token que recibas de la app de la billetera.
El parámetro credential_request
en requestJson
constaría de los siguientes campos.
{
"response_type": "vp_token",
"response_mode": "dc_api.jwt",
"nonce": "1234",
"dcql_query": {
"credentials": [
{
"id": "cred1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL" // this is for mDL. Use com.google.wallet.idcard.1 for ID pass
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"family_name"
]
},
{
"path": [
"org.iso.18013.5.1",
"given_name"
]
},
{
"path": [
"org.iso.18013.5.1",
"age_over_18"
]
}
]
}
]
},
"client_metadata": {
"jwks": {
"keys": [ // sample request encryption key
{
"kty": "EC",
"crv": "P-256",
"x": "pDe667JupOe9pXc8xQyf_H03jsQu24r5qXI25x_n1Zs",
"y": "w-g0OrRBN7WFLX3zsngfCWD3zfor5-NLHxJPmzsSvqQ",
"use": "enc",
"kid" : "1",
"alg" : "ECDH-ES",
}
]
},
"authorization_encrypted_response_alg": "ECDH-ES",
"authorization_encrypted_response_enc": "A128GCM"
}
}
Puedes solicitar la cantidad de atributos admitidos que desees de cualquier credencial de identidad almacenada en la Billetera de Google.
En la app
Para solicitar credenciales de identidad desde tus apps para Android, sigue estos pasos:
Actualiza las dependencias
En el archivo build.gradle de tu proyecto, actualiza las dependencias para usar el Administrador de credenciales (beta):
dependencies {
implementation("androidx.credentials:credentials:1.5.0-beta01")
// optional - needed for credentials support from play services, for devices running Android 13 and below.
implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}
Cómo configurar el Administrador de credenciales
Para configurar e inicializar un objeto CredentialManager
, agrega una lógica similar a la siguiente:
// Use your app or activity context to instantiate a client instance of CredentialManager.
val credentialManager = CredentialManager.create(context)
Solicita atributos de identidad
En lugar de especificar parámetros individuales para las solicitudes de identidad, la app los proporciona todos juntos como una cadena JSON dentro de CredentialOption. Credential Manager pasa esta cadena JSON a las billeteras digitales disponibles sin examinar su contenido. Luego, cada billetera es responsable de lo siguiente: - Analizar la cadena JSON para comprender la solicitud de identidad - Determinar cuáles de sus credenciales almacenadas, si las hay, satisfacen la solicitud
Recomendamos a los socios que creen sus solicitudes en el servidor, incluso para las integraciones de apps para Android.
Usarás requestJson
de Formato de solicitud que consta de request
en la llamada a la función GetDigitalCredentialOption()
// The request in the JSON format to conform with
// the JSON-ified Digital Credentials API request definition.
val requestJson = generateRequestFromServer()
val digitalCredentialOption =
GetDigitalCredentialOption(requestJson = requestJson)
// Use the option from the previous step to build the `GetCredentialRequest`.
val getCredRequest = GetCredentialRequest(
listOf(digitalCredentialOption)
)
coroutineScope.launch {
try {
val result = credentialManager.getCredential(
context = activityContext,
request = getCredRequest
)
verifyResult(result)
} catch (e : GetCredentialException) {
handleFailure(e)
}
}
Verifica y valida la respuesta
Una vez que recibas una respuesta de la billetera, verificarás si la respuesta es exitosa y contiene la respuesta credentialJson
.
// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
val credential = result.credential
when (credential) {
is DigitalCredential -> {
val responseJson = credential.credentialJson
validateResponseOnServer(responseJson) // make a server call to validate the response
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential ${credential.type}")
}
}
}
// Handle failure.
fun handleFailure(e: GetCredentialException) {
when (e) {
is GetCredentialCancellationException -> {
// The user intentionally canceled the operation and chose not
// to share the credential.
}
is GetCredentialInterruptedException -> {
// Retry-able error. Consider retrying the call.
}
is NoCredentialException -> {
// No credential was available.
}
else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
}
}
La respuesta credentialJson
contiene un identityToken (JWT) encriptado, según la definición del W3C. La app de Wallet es responsable de elaborar esta respuesta.
Ejemplo:
{
"protocol" : "openid4vp",
"data" : {
<encrpted_response>
}
}
Pasarás esta respuesta al servidor para validar su autenticidad. Puedes encontrar los pasos para validar la respuesta de la credencial.
Web
Para solicitar credenciales de identidad con la API de Digital Credentials en Chrome, deberás registrarte en la prueba de origen de la API de Digital Credentials.
const credentialResponse = await navigator.credentials.get({
digital : {
requests : [
{
protocol: "openid4vp",
data: {<credential_request>} // This is an object, shouldn't be a string.
}
]
}
})
Envía la respuesta de esta API a tu servidor para validar la respuesta de credenciales.
Pasos para validar la respuesta de credenciales
Cuando recibas el identityToken encriptado de tu app o sitio web, deberás realizar varias validaciones antes de confiar en la respuesta.
Desencripta la respuesta con la clave privada
El primer paso es desencriptar el token con la clave privada guardada y obtener una respuesta JSON.
Ejemplo de Python:
from jwcrypto import jwe, jwk # Retrieve the Private Key from Datastore reader_private_jwk = jwk.JWK.from_json(jwe_private_key_json_str) # Decrypt the JWE encrypted response from Google Wallet jwe_object = jwe.JWE() jwe_object.deserialize(encrypted_jwe_response_from_wallet) jwe_object.decrypt(reader_private_jwk) decrypted_payload_bytes = jwe_object.payload decrypted_data = json.loads(decrypted_payload_bytes)
decrypted_data
generará un objetovp_token
JSON que contendrá la credencial.{ "vp_token": { "cred1": "<credential_token>" } }
Crea la transcripción de la sesión
El siguiente paso es crear el objeto SessionTranscript a partir de ISO/IEC 18013-5:2021 con una estructura de transferencia específica para Android o la Web:
SessionTranscript = [ null, // DeviceEngagementBytes not available null, // EReaderKeyBytes not available [ "OpenID4VPDCAPIHandover", AndroidHandoverDataBytes // BrowserHandoverDataBytes for Web ] ]
Para las transferencias tanto en Android como en la Web, deberás usar el mismo nonce que usaste para generar
credential_request
.Transferencia a Android
AndroidHandoverData = [ origin, // "android:apk-key-hash:<base64SHA256_ofAppSigningCert>", clientId, // "android-origin:<app_package_name>", nonce, // nonce that was used to generate credential request ] AndroidHandoverDataBytes = hashlib.sha256(cbor2.dumps(AndroidHandoverData)).digest()
Transferencia del navegador
BrowserHandoverData =[ origin, // Origin URL clientId, // "web-origin:<origin>" nonce, // nonce that was used to generate credential request ] BrowserHandoverDataBytes = hashlib.sha256(cbor2.dumps(BrowserHandoverData)).digest()
Con
SessionTranscript
, se debe validar el DeviceResponse según la cláusula 9 de ISO/IEC 18013-5:2021. Esto incluye varios pasos, como los siguientes:Verifica el certificado de la entidad emisora del estado. Consulta los certificados de IACA de la entidad emisora admitida
Verifica la firma del MSO (sección 9.1.2 de 18013-5)
Calcula y verifica los ValueDigests para los elementos de datos (sección 9.1.2 de 18013-5)
Verifica la firma de
deviceSignature
(sección 9.1.3 de 18013-5)
{
"version": "1.0",
"documents": [
{
"docType": "org.iso.18013.5.1.mDL",
"issuerSigned": {
"nameSpaces": {...}, // contains data elements
"issuerAuth": [...] // COSE_Sign1 w/ issuer PK, mso + sig
},
"deviceSigned": {
"nameSpaces": 24(<< {} >>), // empty
"deviceAuth": {
"deviceSignature": [...] // COSE_Sign1 w/ device signature
}
}
}
],
"status": 0
}
Prueba tu solución
Para probar tu solución, compila y ejecuta nuestra aplicación para Android de referencia de código abierto. Sigue estos pasos para compilar y ejecutar la app de referencia:
- Clona el repositorio de las apps de referencia.
- Abre el proyecto en Android Studio
- Compila y ejecuta el destino
appholder
en tu dispositivo o emulador Android.
Verificación basada en pruebas de conocimiento cero (ZKP)
La prueba de conocimiento cero (ZKP) es un método criptográfico que permite que una persona (el probador) demuestre a un verificador que posee cierta información de identidad o que cumple con un criterio específico (p.ej., ser mayor de 18 años, tener una credencial válida) sin revelar los datos subyacentes reales. Básicamente, es una forma de confirmar la veracidad de una declaración sobre la identidad de una persona y, al mismo tiempo, mantener privados los detalles sensibles.
Los sistemas de identidad digital que se basan en el uso compartido directo de datos de identidad suelen requerir que los usuarios compartan información personal excesiva, lo que aumenta el riesgo de filtraciones de datos y robo de identidad. Las ZKP ofrecen un cambio de paradigma, ya que permiten la verificación con una divulgación mínima.
Conceptos clave de las ZKP en la identidad digital:
- Verificador: Es la persona que intenta demostrar un aspecto de su identidad.
- Verificador: Es la entidad que solicita la prueba de un atributo de identidad.
- La prueba: Es un protocolo criptográfico que permite que el probador convenza al verificador de la veracidad de su afirmación sin revelar la información secreta.
Propiedades principales de las pruebas de conocimiento cero:
- Integridad: Si la declaración es verdadera y tanto el demostrador como el verificador son honestos, el verificador se convencerá.
- Solidez: Si la declaración es falsa, un demostrador deshonesto no puede (con una probabilidad muy alta) convencer a un verificador honesto de que es verdadera.
- Conocimiento cero: El verificador no aprende nada más allá del hecho de que la declaración es verdadera. No se expone ningún dato real de la identidad del probador.
Para obtener una prueba de conocimiento cero de la Billetera de Google, debes cambiar el formato de la solicitud a mso_mdoc_zk
y agregar zk_system_type
a tu solicitud.
...
"dcql_query": {
"credentials": [{
"id": "cred1",
"format": "mso_mdoc_zk",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
"zk_system_type": [
{
"system": "longfellow-libzk-v1",
"circuit_hash": "2093f64f54c81fb2f7f96a46593951d04005784da3d479e4543e2190dcf205d6", //This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 2
},
{
"system": "longfellow-libzk-v1",
"circuit_hash": "2836f0df5b7c2c431be21411831f8b3d2b7694b025a9d56a25086276161f7a93", // This will differ if you need more than 1 attribute.
"num_attributes": 1, // number of attributes (in claims) this has can support
"version": 1
}
],
"verifier_message": "challenge"
},
"claims": [{
...