Para recibir y almacenar credenciales de las entidades emisoras, tu app de titular debe controlar los flujos de emisión. La emisión de credenciales se puede activar de dos maneras:
- Flujo iniciado por la entidad emisora: El usuario activa una solicitud para emitir una VDC desde una aplicación o un sitio web de la entidad emisora. Por ejemplo, un sitio web puede ofrecer a sus usuarios la opción de "Agregar tu pasaporte a la billetera". La entidad emisora llama a la API de emisión del Administrador de credenciales para realizar una solicitud de oferta de credenciales de OpenID4VCI. Para controlar esas solicitudes, el titular primero debe integrarse con el Administrador de credenciales para registrar sus metadatos. El Administrador de credenciales mostrará opciones pertinentes para que el usuario las seleccione. Después de que el usuario seleccione una opción de titular, se invocará la aplicación del titular, que podrá continuar con los pasos necesarios para completar la emisión.
- Flujo iniciado por el titular: El usuario solicita agregar una VDC desde su aplicación de titular. Por ejemplo, un titular puede ofrecer un botón para "Agregar tu pasaporte". En este caso, el titular mantiene su lista de entidades emisoras admitidas y sus metadatos. No es necesario que se integre con el Administrador de credenciales de Android para completar esta función.
Para obtener más información sobre cómo funcionan las credenciales con la API de Holder, consulta Acerca del almacenamiento de credenciales digitales.
Compatibilidad con versiones de Android
La API de Holder es compatible con Android 6 (nivel de API 23) y versiones posteriores.
Implementación
Para usar la API de Credential Manager Holder, agrega las siguientes dependencias a la secuencia de comandos de compilación del módulo de tu app:
Groovy
dependencies { // Use to implement credentials registrys implementation "androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha04" implementation "androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha04" implementation "androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha04" implementation "androidx.credentials.registry:registry-provider:1.0.0-alpha04" implementation "androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha04" }
Kotlin
dependencies { // Use to implement credentials registrys implementation("androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha04") implementation("androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha04") implementation("androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha04") implementation("androidx.credentials.registry:registry-provider:1.0.0-alpha04") implementation("androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha04") }
Crea el RegistryManager
Crea una instancia de RegistryManager y registra una solicitud de RegisterCreationOptionsRequest con ella.
val registryManager = RegistryManager.create(context)
try {
registryManager.registerCreationOptions(object :
RegisterCreationOptionsRequest(
creationOptions = buildIssuanceData(),
matcher = loadIssuanceMatcher(),
type = DigitalCredential.TYPE_DIGITAL_CREDENTIAL,
id = "openid4vci",
) {}
)
} catch (e: Exception) {
Log.e(TAG, "Issuance registration failed.", e)
}
El comparador es un archivo binario de WebAssembly (Wasm) que recibe el conjunto de creationOptions durante el registro y la oferta de credenciales que envía la entidad emisora para determinar las entradas que se muestran en la IU del Administrador de credenciales. Consulta la app de billetera de ejemplo de código abierto para ver un ejemplo de un comparador.
Controla una solicitud de emisión
A continuación, la billetera debe controlar cuándo el usuario selecciona una opción de creación de credenciales. Define una actividad que escuche el filtro de intents androidx.credentials.registry.provider.action.CREATE_CREDENTIAL, como se muestra en la billetera de ejemplo.
El intent que inicia la actividad contiene la solicitud de creación y el origen de la llamada, que puedes extraer con la función PendingIntentHandler.retrieveProviderCreateCredentialRequest. La API
devuelve un ProviderCreateCredentialRequest que contiene toda la información
asociada con la solicitud de creación. Hay dos componentes clave:
- La app que realizó la solicitud. Puedes recuperarlo con
getCallingAppInfo. - Es la solicitud de la app de llamadas. Puedes recuperarla con
getCallingRequest, que devuelve unCreateCredentialRequest. Si la solicitud es para credenciales digitales, es una instancia deCreateDigitalCredentialRequest, que contiene el JSON de la solicitud de emisión en la propiedadrequestJson. Puedes procesar eso con el siguiente código de muestra:
val pendingIntentRequest =
PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)
val request = pendingIntentRequest!!.callingRequest
if (request is CreateDigitalCredentialRequest) {
Log.i(TAG, "Got DC creation request: ${request.requestJson}")
processCreationRequest(request.requestJson)
}
Certificación de claves
Ten en cuenta lo siguiente sobre la certificación de claves:
- Cuando generas una certificación de claves, es posible que uses
BigInteger.toByteArraypara convertir los materiales de la clave en, por ejemplo, una clave web JSON. A veces, este método puede agregar un byte de signo y causar un error de validación. Si esto sucede, quita estos bytes antes de enviar la certificación de claves al emisor. - Te recomendamos que uses
android_key_attestationcomo el tipo de prueba de clave.
Devuelve la respuesta de creación
Una vez que la billetera complete los pasos necesarios para guardar la credencial, finaliza la actividad con la respuesta de la credencial:
val resultData = Intent()
PendingIntentHandler.setCreateCredentialResponse(
resultData,
CreateDigitalCredentialResponse(response.responseJson)
)
setResult(RESULT_OK, resultData)
finish()
Si hay una excepción, puedes enviar la excepción de credencial de manera similar:
val resultData = Intent()
PendingIntentHandler.setCreateCredentialException(
resultData,
CreateCredentialUnknownException() // Configure the proper exception
)
setResult(RESULT_OK, resultData)
finish()
Para ver un ejemplo completo de cómo devolver la respuesta de credenciales en contexto, consulta la app de ejemplo.