Cómo controlar la emisión de credenciales con tu app de titular

Para recibir y almacenar credenciales de emisores, tu app de titular debe controlar los flujos de emisión. En un flujo de emisión, el sitio web o la app de la entidad emisora envían una oferta de credencial a la app de titular en la que se detallan los datos necesarios para aprovisionar una credencial. La app de titular usa RegistryManager para registrar en Credential Manager los tipos de credenciales que pretende controlar. Esto permite que la app se muestre al usuario y que este la seleccione durante una solicitud de emisión para recibir la credencial.

Para obtener más información sobre cómo funcionan las credenciales con la API de Holder, lee los conceptos básicos de la API de Holder.

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 Holder de Credential Manager, 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")

}

Cómo crear el RegistryManager

Crea una instancia de RegistryManager y registra una solicitud 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 recibirá el creationOptions establecido durante el registro y la oferta de credenciales que envía la entidad emisora para determinar las entradas que se muestran en la IU de Credential Manager. 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 detecte 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 muestra 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 recuperarla con `getCallingAppInfo`. Puedes recuperar este valor con getCallingAppInfo.
  • La solicitud de la app que realiza la llamada. Puedes recuperarla con getCallingRequest, que muestra un CreateCredentialRequest. Si la solicitud es para credenciales digitales, es una instancia de CreateDigitalCredentialRequest, que contiene el JSON de la solicitud de emisión en la propiedad requestJson. Puedes procesarlo 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 generes una certificación de claves, es posible que uses BigInteger.toByteArray() para convertir los materiales de la clave, por ejemplo, en 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.
  • Recomendamos usar android_key_attestation como el tipo de prueba de clave.

Muestra 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 mostrar la respuesta de la credencial en contexto, consulta la app de ejemplo.