验证数字凭据

Android 应用中的数字凭据验证可用于验证和授权用户的身份(例如政府签发的身份证件)、用户的相关属性(例如驾照、学位或年龄或地址等属性),或在需要签发和验证凭据以断言实体真实性的情况下。

数字凭据是公开的 W3C 孵化器标准,用于指定如何从数字钱包访问用户的可验证数字凭据,并通过 W3C Credential Management API 实现 Web 用例。在 Android 上,Credential Manager 的 DigitalCredential API 用于验证数字凭据。

实现

如需在 Android 项目中验证数字凭据,请执行以下操作:

  1. 将依赖项添加到应用的 build 脚本中,并初始化 CredentialManager 类。
  2. 构建数字凭据请求,并使用该请求初始化 DigitalCredentialOption,然后构建 GetCredentialRequest
  3. 使用构建的请求启动 getCredential 流程,以接收成功的 GetCredentialResponse 或处理可能发生的任何异常。检索成功后,验证响应。

添加依赖项并进行初始化

将以下依赖项添加到 Gradle build 脚本中:

dependencies {
    implementation("androidx.credentials:credentials:1.5.0-beta01")
    implementation("androidx.credentials:credentials-play-services-auth:1.5.0-beta01")
}

接下来,初始化 CredentialManager 类的实例。

val credentialManager = CredentialManager.create(context)

构建数字凭据请求

构建数字凭据请求,并使用该请求初始化 DigitalCredentialOption

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

获取凭据

使用构建的请求启动 getCredential 流程。如果请求成功,您会收到 GetCredentialResponse;如果请求失败,则会收到 GetCredentialException

getCredential 流程会触发 Android 系统对话框,以显示用户可用的凭据选项并收集其选择。接下来,包含所选凭据选项的钱包应用将显示界面,以收集用户同意,并执行生成数字凭据响应所需的操作。

coroutineScope.launch {
    try {
        val result = credentialManager.getCredential(
            context = activityContext,
            request = getCredRequest
        )
        verifyResult(result)
    } catch (e : GetCredentialException) {
        handleFailure(e)
    }
}

// Handle the successfully returned credential.
fun verifyResult(result: GetCredentialResponse) {
    val credential = result.credential
    when (credential) {
        is DigitalCredential -> {
            val responseJson = credential.credentialJson
            validateResponseOnServer(responseJson)
        }
        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.
        }
        is CreateCredentialUnknownException -> {
            // An unknown, usually unexpected, error has occurred. Check the
            // message error for any additional debugging information.
        }
        is CreateCredentialCustomException -> {
            // You have encountered a custom error thrown by the wallet.
            // If you made the API call with a request object that's a
            // subclass of CreateCustomCredentialRequest using a 3rd-party SDK,
            // then you should check for any custom exception type constants
            // within that SDK to match with e.type. Otherwise, drop or log the
            // exception.
        }
        else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
    }
}