Gerenciador de credenciais: API Verifier

A verificação de credenciais digitais em apps Android pode ser usada para autenticar e autorizar a identidade de um usuário (como um documento de identificação oficial), propriedades sobre esse usuário (como uma carteira de habilitação, um diploma acadêmico ou atributos como idade ou endereço) ou outros cenários em que uma credencial precisa ser emitida e verificada para confirmar a autenticidade de uma entidade.

As credenciais digitais são um padrão público do W3C que especifica como acessar as credenciais digitais verificáveis de um usuário em uma carteira digital. Elas são implementadas para casos de uso da Web com a API Credential Management do W3C. No Android, a API DigitalCredential do Gerenciador de credenciais é usada para verificar credenciais digitais.

Implementação

Para verificar credenciais digitais no seu projeto Android, faça o seguinte:

  1. Adicione dependências ao script de build do app e inicialize uma classe CredentialManager.
  2. Construa uma solicitação de credencial digital e use-a para inicializar um DigitalCredentialOption, seguido da criação do GetCredentialRequest.
  3. Inicie o fluxo getCredential com a solicitação criada para receber um GetCredentialResponse bem-sucedido ou processe as exceções que possam ocorrer. Após a recuperação, valide a resposta.

Adicionar dependências e inicializar

Adicione as seguintes dependências ao script de build do Gradle:

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

Em seguida, inicialize uma instância da classe CredentialManager.

val credentialManager = CredentialManager.create(context)

Criar uma solicitação de credencial digital

Construa uma solicitação de credencial digital e use-a para inicializar um DigitalCredentialOption.

// The request in the JSON format to conform with
// the JSON-ified Credential Manager - Verifier 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)
)

Confira um exemplo de solicitação OpenId4Vp. Confira uma referência completa neste site.

{
  "requests": [
    {
      "protocol": "openid4vp-v1-unsigned",
      "data": {
        "response_type": "vp_token",
        "response_mode": "dc_api",
        "nonce": "OD8eP8BYfr0zyhgq4QCVEGN3m7C1Ht_No9H5fG5KJFk",
        "dcql_query": {
          "credentials": [
            {
              "id": "cred1",
              "format": "mso_mdoc",
              "meta": {
                "doctype_value": "org.iso.18013.5.1.mDL"
              },
              "claims": [
                {
                  "path": [
                    "org.iso.18013.5.1",
                    "family_name"
                  ]
                },
                {
                  "path": [
                    "org.iso.18013.5.1",
                    "given_name"
                  ]
                },
                {
                  "path": [
                    "org.iso.18013.5.1",
                    "age_over_21"
                  ]
                }
              ]
            }
          ]
        }
      }
    }
  ]
}

Receber a credencial

Inicie o fluxo getCredential com a solicitação criada. Você vai receber um GetCredentialResponse de sucesso ou um GetCredentialException se a solicitação falhar.

O fluxo getCredential aciona caixas de diálogo do sistema Android para apresentar as opções de credenciais disponíveis ao usuário e coletar a seleção dele. Em seguida, o app de carteira que contém a opção de credencial escolhida vai mostrar interfaces para coletar consentimento e realizar as ações necessárias para gerar uma resposta de credencial digital.

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