凭据管理器 - 持有者 API

Credential Manager - 持有者 API 让 Android 应用能够管理数字凭据并将其提供给验证者。

开始

要使用 Credential Manager - 持有者 API,请将以下依赖项添加到您的应用模块构建脚本中

// In your app module's build.gradle:
dependencies {
    implementation(libs.androidx.registry.provider)
    implementation(libs.androidx.registry.provider.play.services)
}

// In libs.versions.toml:
registryDigitalCredentials = "1.0.0-alpha01"

androidx-registry-provider = { module = "androidx.credentials.registry:registry-provider", version.ref = "registryDigitalCredentials" }
androidx-registry-provider-play-services = { module = "androidx.credentials.registry:registry-provider-play-services", version.ref = "registryDigitalCredentials" }

使用凭据管理器注册凭据

钱包需要注册凭据元数据,以便凭据管理器在收到请求时能够过滤并在凭据选择器中显示这些凭据。

Image showing the digital credentials UI in Credential Manager
图 1. 数字凭据界面。

凭据管理器选择器界面

此元数据的格式会传递给 RegisterCredentialsRequest。创建 [RegistryManager][1] 并注册凭据

在此示例中,元数据是从凭据条目数据库编译而来的。您可以在我们的示例钱包中找到参考,该示例会在应用加载时注册元数据。将来,Jetpack API 将支持凭据数据库组合。届时,您可以将凭据元数据注册为定义良好的数据结构。

注册表会跨设备重启持久存在。重新注册相同 ID + 相同类型的注册表将覆盖之前的注册表记录。因此,您只需在凭据数据发生更改时才需要重新注册。

可选:创建匹配器

凭据管理器是协议无关的;它将元数据注册表视为一个不透明的 blob,并且不验证或检查其内容。因此,钱包必须提供一个匹配器,它是一个可运行的二进制文件,可以处理钱包自身的数据,并根据传入请求生成显示元数据。凭据管理器将在没有网络或磁盘访问权限的沙盒环境中运行匹配器,以便在向用户渲染 UI 之前,不会有任何信息泄露到钱包中。

Credential Manager API 将为流行协议提供匹配器,目前是 OpenID4VP。它尚未正式发布,因此目前请使用我们的示例匹配器用于 OpenID4VP v24 协议

处理选定的凭据

接下来,钱包需要处理用户选择凭据的情况。您可以定义一个 Activity,用于监听 androidx.credentials.registry.provider.action.GET_CREDENTIAL Intent 过滤器。我们的示例钱包演示了此过程

启动该 Activity 的 Intent 将包含验证者请求和调用来源,这可以使用 PendingIntentHandler.retrieveProviderGetCredentialRequest 函数进行提取。该 API 会返回一个 ProviderGetCredentialRequest,其中包含与给定验证者请求相关的所有信息。有三个关键组件

最常见的情况是,验证者将发起数字凭据的呈现请求,因此您可以使用以下示例代码进行处理

request.credentialOptions.forEach { option ->
    if (option is GetDigitalCredentialOption) {
        Log.i(TAG, "Got DC request: ${option.requestJson}")
        processRequest(option.requestJson)
    }
}

您可以在我们的示例钱包中看到此示例

渲染钱包界面

选择凭据后,将调用钱包并引导用户完成其 UI。在示例中,这是一个生物识别提示

返回凭据响应

一旦钱包准备好返回结果,您可以通过完成 Activity 并附带凭据响应来做到这一点

PendingIntentHandler.setGetCredentialResponse(
    resultData,
    GetCredentialResponse(DigitalCredential(response.responseJson))
)
setResult(RESULT_OK, resultData)
finish()

如果出现异常,您也可以类似地发送凭据异常

PendingIntentHandler.setGetCredentialException(
    resultData,
    GetCredentialUnknownException() // Configure the proper exception
)
setResult(RESULT_OK, resultData)
finish()

有关如何在上下文中返回凭据响应的示例,请参阅示例应用