No Android 15, o Credential Manager oferece suporte a um fluxo de toque único para criação e recuperação de credenciais. Nesse fluxo, as informações da credencial que está sendo criada ou usada são mostradas diretamente na solicitação biométrica, junto com um ponto de entrada para mais opções. Esse processo simplificado cria um processo mais eficiente e simplificado de criação e recuperação de credenciais.
Requisitos:
- A biometria foi configurada no dispositivo do usuário, e ele permite que ela seja usada para autenticação em aplicativos.
- Para fluxos de login, esse recurso é ativado apenas para cenários de conta única, mesmo que haja várias credenciais (como chave de acesso e senha) disponíveis para essa conta.
Ativar o toque único nos fluxos de criação de chaves de acesso
As etapas de criação desse método correspondem ao processo de criação de credenciais
existente. No BeginCreatePublicKeyCredentialRequest, use
handleCreatePasskeyQuery() para processar a solicitação se ela for para uma chave de acesso.
is BeginCreatePublicKeyCredentialRequest -> {
Log.i(TAG, "Request is passkey type")
return handleCreatePasskeyQuery(request, passwordCount, passkeyCount)
}
No handleCreatePasskeyQuery(), inclua BiometricPromptData com
a classe CreateEntry:
val createEntry = CreateEntry(
// Additional properties...
biometricPromptData = BiometricPromptData(
allowedAuthenticators = allowedAuthenticator
),
)
Os provedores de credenciais precisam definir explicitamente a propriedade allowedAuthenticator
na instância BiometricPromptData. Se essa propriedade não for definida, o valor
padrão será DEVICE_WEAK. Defina a propriedade opcional cryptoObject, se necessário,
para seu caso de uso.
Ativar o toque único nos fluxos de login com chave de acesso
Assim como no fluxo de criação de chaves de acesso, isso vai seguir a configuração atual para
processar o login do usuário. Em BeginGetPublicKeyCredentialOption, use
populatePasskeyData() para coletar as informações relevantes sobre a
solicitação de autenticação:
is BeginGetPublicKeyCredentialOption -> {
// ... other logic
populatePasskeyData(
origin,
option,
responseBuilder,
autoSelectEnabled,
allowedAuthenticator
)
// ... other logic as needed
}
Semelhante a CreateEntry, uma instância BiometricPromptData é definida como a
instância PublicKeyCredentialEntry. Se não estiver definido explicitamente,
allowedAuthenticator assumirá como padrão BIOMETRIC_WEAK.
PublicKeyCredentialEntry(
// other properties...
biometricPromptData = BiometricPromptData(
allowedAuthenticators = allowedAuthenticator
)
)
Processar a seleção de entrada de credencial
Ao processar a seleção de entrada de credenciais para criar uma chave de acesso ou
selecionar uma chave de acesso durante o login, chame PendingIntentHandler's
retrieveProviderCreateCredentialRequest ou
retrieveProviderGetCredentialRequest, conforme apropriado. Eles retornam objetos
que contêm os metadados necessários para o provedor. Por exemplo, ao processar
a seleção de entrada de criação de chave de acesso, atualize o código da seguinte forma:
val createRequest = PendingIntentHandler.retrieveProviderCreateCredentialRequest(intent)
if (createRequest == null) {
Log.i(TAG, "request is null")
setUpFailureResponseAndFinish("Unable to extract request from intent")
return
}
// Other logic...
val biometricPromptResult = createRequest.biometricPromptResult
// Add your logic based on what needs to be done
// after getting biometrics
if (createRequest.callingRequest is CreatePublicKeyCredentialRequest) {
val publicKeyRequest: CreatePublicKeyCredentialRequest =
createRequest.callingRequest as CreatePublicKeyCredentialRequest
if (biometricPromptResult == null) {
// Do your own authentication flow, if needed
} else if (biometricPromptResult.isSuccessful) {
createPasskey(
publicKeyRequest.requestJson,
createRequest.callingAppInfo,
publicKeyRequest.clientDataHash,
accountId
)
} else {
val error = biometricPromptResult.authenticationError
// Process the error
}
// Other logic...
}
Este exemplo contém informações sobre o sucesso do fluxo biométrico. Ele também
contém outras informações sobre a credencial. Se o fluxo falhar, use o
código do erro em biometricPromptResult.authenticationError para tomar decisões.
Os códigos de erro retornados como parte de
biometricPromptResult.authenticationError.errorCode são os mesmos códigos de erro
definidos na biblioteca androidx.biometric, como
androidx.biometric.BiometricPrompt.ERROR_NO_SPACE,
androidx.biometric.BiometricPrompt.ERROR_UNABLE_TO_PROCESS,
androidx.biometric.BiometricPrompt.ERROR_TIMEOUT e semelhantes. O
authenticationError também vai conter uma mensagem de erro associada ao
errorCode que pode ser mostrada em uma interface.
Da mesma forma, extraia metadados durante o retrieveProviderGetCredentialRequest.
Verifique se o fluxo biométrico é null. Se sim, configure sua própria biometria para
autenticação. Isso é semelhante à forma como a operação get é instrumentada:
val getRequest =
PendingIntentHandler.retrieveProviderGetCredentialRequest(intent)
if (getRequest == null) {
Log.i(TAG, "request is null")
setUpFailureResponseAndFinish("Unable to extract request from intent")
return
}
// Other logic...
val biometricPromptResult = getRequest.biometricPromptResult
// Add your logic based on what needs to be done
// after getting biometrics
if (biometricPromptResult == null) {
// Do your own authentication flow, if necessary
} else if (biometricPromptResult.isSuccessful) {
Log.i(TAG, "The response from the biometricPromptResult was ${biometricPromptResult.authenticationResult?.authenticationType}")
validatePasskey(
publicKeyRequest.requestJson,
origin,
packageName,
uid,
passkey.username,
credId,
privateKey
)
} else {
val error = biometricPromptResult.authenticationError
// Process the error
}
// Other logic...