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 carteira de habilitação, diploma 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 e são implementadas
para casos de uso da Web com a API W3C Credential Management. No
Android, a API DigitalCredential
do Gerenciador de credenciais é usada para
verificar credenciais digitais.
Implementação
Para verificar as credenciais digitais no seu projeto 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 a use para inicializar um
DigitalCredentialOption
, seguido pela criação doGetCredentialRequest
. - Inicie o fluxo
getCredential
com a solicitação construída para receber umaGetCredentialResponse
bem-sucedida 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:")
implementation("androidx.credentials:credentials-play-services-auth:")
}
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 a use para inicializar um
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)
)
Confira um exemplo de solicitação do OpenId4Vp. A referência completa pode ser encontrada neste site.
{
"digital": {
"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
credencial disponíveis do 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 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.
}
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}")
}
}