Как обрабатывать выдачу удостоверений с помощью приложения-кошелька

Чтобы получать и хранить удостоверения личности от эмитентов, приложение-кошелек должно поддерживать процессы выпуска. Выпуск учетных данных можно запустить двумя способами:

  • Процесс, инициированный эмитентом. Пользователь запрашивает выпуск виртуальной карты в приложении или на сайте эмитента. Например, на сайте может быть кнопка "Добавить паспорт в Кошелек". Эмитент вызывает API выдачи Менеджера учетных данных, чтобы отправить запрос на предложение учетных данных OpenID4VCI. Чтобы обрабатывать такие запросы, держатель должен сначала интегрироваться с Менеджером учетных данных и зарегистрировать свои метаданные. Менеджер учетных данных покажет пользователю подходящие варианты. После того как пользователь выберет приложение, оно будет запущено и сможет выполнить необходимые действия для завершения выпуска.
  • Процесс, инициированный держателем. Пользователь запрашивает добавление виртуальной карты из приложения держателя. Например, на сайте может быть кнопка "Добавить паспорт". В этом случае держатель поддерживает список эмитентов и метаданные. Для этого не требуется интеграция с Менеджером учетных данных Android.

Подробнее о том, как удостоверения работают с Holder API, рассказывается в статье О хранении цифровых удостоверений.

Совместимость с версиями Android

Holder API поддерживается на устройствах с Android 6 (уровень API 23) и более поздними версиями.

Реализация

Чтобы использовать Credential Manager Holder API, добавьте в скрипт сборки модуля приложения следующие зависимости:

классный

dependencies {
    // Use to implement credentials registrys

    implementation "androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha05"
    implementation "androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha05"
    implementation "androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha05"
    implementation "androidx.credentials.registry:registry-provider:1.0.0-alpha05"
    implementation "androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha05"

}

Котлин

dependencies {
    // Use to implement credentials registrys

    implementation("androidx.credentials.registry:registry-digitalcredentials-mdoc:1.0.0-alpha05")
    implementation("androidx.credentials.registry:registry-digitalcredentials-openid:1.0.0-alpha05")
    implementation("androidx.credentials.registry:registry-digitalcredentials-sdjwtvc:1.0.0-alpha05")
    implementation("androidx.credentials.registry:registry-provider:1.0.0-alpha05")
    implementation("androidx.credentials.registry:registry-provider-play-services:1.0.0-alpha05")

}

Создайте RegistryManager

Создайте экземпляр RegistryManager и зарегистрируйте в нем запрос RegisterCreationOptionsRequest.

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)
}

Сопоставитель – это двоичный файл WebAssembly (Wasm), который получает набор creationOptions, заданный при регистрации, и предложение учетных данных, отправленное издателем, чтобы определить, какие записи будут показаны в интерфейсе Менеджера учетных данных. Пример сопоставителя можно найти в приложении Кошелька с открытым исходным кодом.

Как обработать запрос на выпуск

Затем кошелек должен обработать выбор пользователем варианта создания учетных данных. Определите действие, которое прослушивает фильтр интентов androidx.credentials.registry.provider.action.CREATE_CREDENTIAL, как показано в примере кошелька.

Интент, запускающий действие, содержит запрос на создание и источник вызова, который можно извлечь с помощью функции PendingIntentHandler.retrieveProviderCreateCredentialRequest . API возвращает объект ProviderCreateCredentialRequest, содержащий всю информацию, связанную с запросом на создание. Она состоит из двух основных компонентов:

  • Приложение, которое отправило запрос. Его можно получить с помощью метода getCallingAppInfo.
  • Запрос от вызывающего приложения. Его можно получить с помощью метода getCallingRequest, который возвращает объект CreateCredentialRequest. Если запрос предназначен для цифровых удостоверений, это экземпляр CreateDigitalCredentialRequest, который содержит JSON запроса на выдачу в свойстве requestJson. Вы можете обработать его с помощью следующего образца кода:
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)
}

Аттестация ключей

Обратите внимание на следующее:

  • При создании аттестации ключей вы можете использовать BigInteger.toByteArray, чтобы преобразовать материалы ключа, например, в веб-ключ JSON. Иногда этот метод может добавить байт знака и вызвать ошибку проверки. В этом случае удалите эти байты перед отправкой аттестации ключа эмитенту.
  • Рекомендуем использовать android_key_attestation в качестве основного типа подтверждения.

Возврат ответа о создании

После того как кошелек выполнит шаги, необходимые для сохранения учетных данных, завершите действие с ответом учетных данных:

val resultData = Intent()
PendingIntentHandler.setCreateCredentialResponse(
    resultData,
    CreateDigitalCredentialResponse(response.responseJson)
)
setResult(RESULT_OK, resultData)
finish()

Если возникает исключение, вы можете отправить исключение учетных данных:

val resultData = Intent()
PendingIntentHandler.setCreateCredentialException(
    resultData,
    CreateCredentialUnknownException() // Configure the proper exception
)
setResult(RESULT_OK, resultData)
finish()

Полный пример возврата ответа с учетными данными в контексте можно найти в примере приложения.