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 identidade oficial), propriedades sobre esse usuário (como uma carteira de habilitação, 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.
A API Verifier é compatível com o Android 9 (nível 28 da API) e versões mais recentes.
Implementação
Para verificar as credenciais digitais no seu projeto do Android, faça o seguinte:
- Adicione dependências ao script de build do app e inicialize uma
classe
CredentialManager. - Crie uma solicitação de credencial digital e use-a para inicializar um
DigitalCredentialOption, seguido pela criação doGetCredentialRequest. - Inicie o fluxo
getCredentialcom a solicitação criada para receber umGetCredentialResponsebem-sucedido ou processar 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
Crie 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)
)
O exemplo a seguir demonstra uma solicitação OpenId4Vp1. Para detalhes sobre os campos nessa solicitação, consulte a documentação do OpenID.
{
"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 bem-sucedido 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 do usuário e coletar a seleção. Em seguida, o app de carteira
que contém a opção de credencial escolhida vai mostrar interfaces para coletar o 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.
}
else -> Log.w(TAG, "Unexpected exception type ${e::class.java}")
}
}
Solicitações flexíveis de várias credenciais
A API Digital Credentials também permite solicitar vários tipos de credenciais de uma só vez usando o OpenID4VP:
- Solicitações simultâneas: solicite várias credenciais em uma única transação do usuário. Por exemplo, um app de viagens pode solicitar um cartão de embarque e um documento de identificação oficial simultaneamente, permitindo que o usuário revise e autorize ambos com um único toque.
- Atendimento flexível: aceite qualquer um dos vários tipos de credenciais ou emissores. Por exemplo, um fluxo de confirmação de idade pode aceitar uma carteira de motorista ou um passaporte, permitindo que os usuários atendam à solicitação usando qualquer credencial armazenada no titular.
Veja um exemplo de como solicitar várias credenciais em uma única solicitação:
{
"credentials": [
{
"id": "gov_id1",
"format": "mso_mdoc",
"meta": {
"doctype_value": "org.iso.18013.5.1.mDL"
},
"claims": [
{
"path": [
"org.iso.18013.5.1",
"age_over_21"
]
}
]
},
{
"id": "boarding_pass1",
"format": "dc+sd-jwt",
"meta": {
"vct_values": [
"https://credentials.example.airline/boarding-pass"
]
},
"claims": [
{
"path": [
"flight_number"
]
},
{
"path": [
"seat"
]
}
]
}
]
}
Processar a resposta
Depois de fazer a solicitação de credencial, processe o GetCredentialResponse
retornado de CredentialManager.
// 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}")
}
}
}
Tratar exceções
O app precisa processar os erros que podem ser gerados, incluindo se não houver credenciais no dispositivo ou se o usuário cancelar a operação:
// 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}")
}
}