Antes que os usuários possam se autenticar com chaves de acesso, seu app precisa registrar ou criar a chave de acesso para a conta deles.
Para criar a chave de acesso, obtenha os detalhes necessários no servidor do app e chame a API Credential Manager, que retorna um par de chaves pública e privada. A chave privada retornada é armazenada em um provedor de credenciais, como o Gerenciador de senhas do Google, como uma chave de acesso. A chave pública é armazenada no servidor de apps.
Pré-requisitos
Verifique se você configurou os Links de recursos digitais e se está segmentando dispositivos com o Android 9 (nível 28 da API) ou versões mais recentes.
Visão geral
Este guia se concentra nas mudanças necessárias no app cliente da parte confiável para criar uma chave de acesso e oferece uma breve visão geral da implementação do servidor do app da parte confiável. Para saber mais sobre a integração do lado do servidor, consulte Registro de chaves de acesso no lado do servidor.
- Adicione dependências ao app: adicione as bibliotecas necessárias do Credential Manager.
- Instanciar o Credential Manager: crie uma instância do Credential Manager.
- Receber opções de criação de credenciais do servidor de apps: do servidor de apps, envie ao app cliente os detalhes necessários para criar a chave de acesso, como informações sobre o app, o usuário, além de um
challengee outros campos. - Solicitar uma chave de acesso: no seu app, use os detalhes recebidos do servidor
do app para criar um objeto
GetPublicKeyCredentialOptione use esse objeto para invocar o métodocredentialManager.getCredential()e criar uma chave de acesso. - Processar a resposta de criação da chave de acesso: quando você recebe as credenciais no app cliente, é necessário codificar, serializar e enviar a chave pública para o servidor do app. Também é necessário processar cada uma das exceções que podem ocorrer em caso de criação de chaves de acesso.
- Verifique e salve a chave pública no servidor: conclua as etapas do lado do servidor para verificar a origem da credencial e salve a chave pública.
- Notificar o usuário: informe ao usuário que a chave de acesso foi criada.
1. Adicionar dependências ao app
Adicione as seguintes dependências ao arquivo build.gradle do módulo do app:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.6.0-beta03") implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta03") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.6.0-beta03" implementation "androidx.credentials:credentials-play-services-auth:1.6.0-beta03" }
2. Instanciar o Credential Manager
Use o contexto do app ou da atividade para criar um objeto CredentialManager.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
3. Receber opções de criação de credenciais do servidor de apps
Quando o usuário clicar em um botão "Criar chave de acesso" ou quando um novo usuário se inscrever, faça uma solicitação do seu app para o servidor dele e obtenha as informações necessárias para iniciar o processo de registro da chave de acesso.
Use uma biblioteca compatível com FIDO no servidor do app para enviar ao app cliente as informações necessárias para criar uma chave de acesso, como informações sobre o usuário, o app e outras propriedades de configuração. Para saber mais, consulte Registro de chaves de acesso no lado do servidor.
No app cliente, decodifique as opções de criação de chave pública enviadas pelo servidor do app. Eles geralmente são representados no formato JSON. Para saber mais sobre como essa decodificação é feita para clientes da Web, consulte Codificação e decodificação. Para apps clientes Android, é necessário processar a decodificação separadamente.
O snippet a seguir mostra a estrutura das opções de criação de chave pública enviadas pelo servidor de apps:
{
"challenge": "<base64url-encoded challenge>",
"rp": {
"name": "<relying party name>",
"id": "<relying party host name>"
},
"user": {
"id": "<base64url-encoded user ID>",
"name": "<user name>",
"displayName": "<user display name>"
},
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
}
],
"attestation": "none",
"excludeCredentials": [
{
"id": "<base64url-encoded credential ID to exclude>",
"type": "public-key"
}
],
"authenticatorSelection": {
"requireResidentKey": true,
"residentKey": "required",
"userVerification": "required"
}
}
Os principais campos nas opções de criação de chave pública incluem:
challenge: uma string aleatória gerada pelo servidor usada para evitar ataques de repetição.rp: detalhes sobre o app.rp.name: o nome do app.rp.id: o domínio ou subdomínio do app.
user: detalhes sobre o usuário.id: o ID exclusivo do usuário. Esse valor não pode incluir informações de identificação pessoal, por exemplo, endereços de e-mail ou nomes de usuário. É possível usar um valor aleatório de 16 bytes.name: um identificador exclusivo da conta que o usuário vai reconhecer, como o endereço de e-mail ou o nome de usuário. Ele vai aparecer no seletor de contas. Se estiver usando um nome de usuário, use o mesmo valor da autenticação por senha.displayName: um nome opcional e fácil de usar para a conta, destinado a exibição no seletor de contas.
authenticatorSelection: detalhes sobre o dispositivo que será usado para autenticação.authenticatorAttachment: indica o autenticador preferido. Os valores possíveis são: -platform: usado para um autenticador integrado ao dispositivo do usuário, como um sensor de impressão digital. -cross-platform: esse valor é usado para dispositivos em roaming, como chaves de segurança. Normalmente, ele não é usado no contexto de chaves de acesso. - Não especificado (recomendado): deixar esse valor não especificado oferece aos usuários a flexibilidade de criar chaves de acesso nos dispositivos preferidos. Na maioria dos casos, deixar o parâmetro não especificado é a melhor opção.requireResidentKey: para criar uma chave de acesso, defina o valor do campoBooleancomotrue.residentKey: para criar uma chave de acesso, defina o valor comorequired.userVerification: usado para especificar os requisitos de verificação do usuário durante o registro de uma chave de acesso. Os valores possíveis são: -preferred: use esse valor se você priorizar a experiência do usuário em vez da proteção, como em ambientes em que a verificação do usuário causa mais atrito do que proteção. -required: use esse valor se for necessário invocar um método de verificação do usuário disponível no dispositivo. -discouraged: use esse valor se não for recomendável usar um método de verificação do usuário.
Para saber mais sobreuserVerification, consulte detalhamento da userVerification.
excludeCredentials: liste os IDs de credenciais em uma matriz para evitar a criação de uma chave de acesso duplicada se já existir uma com o mesmo provedor de credenciais.
4. Pedir uma chave de acesso
Depois de analisar as opções de criação de chave pública do lado do servidor, crie uma
chave de acesso encapsulando essas opções em um objeto CreatePublicKeyCredentialRequest
e chamando createCredential().
O createPublicKeyCredentialRequest inclui o seguinte:
requestJson: as opções de criação de credenciais enviadas pelo servidor de apps.preferImmediatelyAvailableCredentials: um campo booleano opcional que define se apenas credenciais disponíveis localmente ou sincronizadas pelo provedor de credenciais serão usadas para atender à solicitação, em vez de credenciais de chaves de segurança ou fluxos de chaves híbridos. Os possíveis usos são os seguintes:false(padrão): use esse valor se a chamada para o Gerenciador de credenciais tiver sido acionada por uma ação explícita do usuário.true: use esse valor se o Gerenciador de credenciais for chamado de forma oportunista, como ao abrir o app pela primeira vez.
Se você definir o valor comotruee não houver credenciais disponíveis imediatamente, o Gerenciador de credenciais não vai mostrar nenhuma interface e a solicitação vai falhar imediatamente, retornando NoCredentialException para solicitações GET eCreateCredentialNoCreateOptionExceptionpara solicitações de criação.
origin: esse campo é definido automaticamente para apps Android. Para navegadores e apps privilegiados semelhantes que precisam definirorigin, consulte Fazer chamadas do Gerenciador de credenciais em nome de terceiros para apps privilegiados.isConditional: este é um campo opcional que tem como padrãofalse. Quando você define isso comotruee um usuário não tem uma chave de acesso, criamos uma automaticamente em nome dele na próxima vez que ele fizer login com uma senha salva. A chave de acesso é armazenada no provedor de credenciais do usuário. O recurso de criação condicional exige a versão mais recente doandroidx.credentials.
Chamar a função createCredential() inicia a interface integrada
da folha inferior do Credential Manager, que pede ao usuário para usar uma chave de acesso e selecionar um
provedor de credenciais e uma conta para armazenamento. No entanto, se isConditional estiver definido como true, a interface da folha inferior não será mostrada, e a chave de acesso será criada automaticamente.
5. Processar a resposta
Depois que o usuário é verificado usando o bloqueio de tela do dispositivo, uma chave de acesso é criada e armazenada no provedor de credenciais selecionado pelo usuário.
A resposta depois de chamar createCredential() é um objeto
PublicKeyCredential.
O PublicKeyCredential tem esta aparência:
{
"id": "<identifier>",
"type": "public-key",
"rawId": "<identifier>",
"response": {
"clientDataJSON": "<ArrayBuffer encoded object with the origin and signed challenge>",
"attestationObject": "<ArrayBuffer encoded object with the public key and other information.>"
},
"authenticatorAttachment": "platform"
}
No app cliente, serializa o objeto e envia para o servidor do app.
Adicione código para processar falhas, conforme mostrado no snippet a seguir:
fun handleFailure(e: CreateCredentialException) {
when (e) {
is CreatePublicKeyCredentialDomException -> {
// Handle the passkey DOM errors thrown according to the
// WebAuthn spec.
}
is CreateCredentialCancellationException -> {
// The user intentionally canceled the operation and chose not
// to register the credential.
}
is CreateCredentialInterruptedException -> {
// Retry-able error. Consider retrying the call.
}
is CreateCredentialProviderConfigurationException -> {
// Your app is missing the provider configuration dependency.
// Most likely, you're missing the
// "credentials-play-services-auth" module.
}
is CreateCredentialCustomException -> {
// You have encountered an error from a 3rd-party SDK. If you
// make 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.name}")
}
}
6. Verificar e salvar a chave pública no servidor de apps
No servidor de apps, verifique a credencial de chave pública e salve a chave pública.
Para verificar a origem da credencial de chave pública, compare-a com uma lista de permissões de apps aprovados. Se uma chave tiver uma origem não reconhecida, rejeite-a.
Para conferir a impressão digital SHA-256 do app:
Imprima o certificado de assinatura do app de lançamento executando o seguinte comando em um terminal:
keytool -list -keystore <path-to-apk-signing-keystore>Na resposta, identifique a impressão digital SHA 256 do certificado de assinatura, mencionada como
Certificate fingerprints block:SHA256.Codifique a impressão digital SHA256 com a codificação base64url. Este exemplo em Python demonstra como codificar corretamente a impressão digital:
import binascii import base64 fingerprint = '<SHA256 finerprint>' # your app's SHA256 fingerprint print(base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))Adicione
android:apk-key-hash: ao início da saída da etapa anterior para ter algo semelhante a isto:android:apk-key-hash:<encoded SHA 256 fingerprint>O resultado precisa corresponder a uma origem permitida no servidor do app. Se você tiver vários certificados de assinatura, como certificados para depuração e lançamento, ou vários apps, repita o processo e aceite todas as origens como válidas no servidor de apps.
7. Notificar o usuário
Depois que a chave de acesso for criada, notifique os usuários sobre ela e informe que é possível gerenciar as chaves de acesso no app do provedor de credenciais ou nas configurações do app. Notifique os usuários usando uma caixa de diálogo, notificação ou snackbar personalizada. Como a criação inesperada de uma chave de acesso por uma entidade maliciosa exige um alerta de segurança imediato, considere complementar esses métodos no app com comunicação externa, como um e-mail.
Melhore a experiência do usuário
Para melhorar a experiência do usuário ao implementar o registro com o Credential Manager, considere adicionar funcionalidades para restaurar credenciais e suprimir caixas de diálogo de preenchimento automático.
Adicionar funcionalidade para restaurar credenciais em um novo dispositivo
Para permitir que os usuários façam login nas contas em um novo dispositivo sem problemas, implemente
a funcionalidade Restaurar credenciais. Ao adicionar credenciais de restauração com
BackupAgent, os usuários fazem login quando abrem o app restaurado em um novo dispositivo,
permitindo que eles usem o app imediatamente.
Suprimir o preenchimento automático nos campos de credenciais (opcional)
Para telas de apps em que os usuários devem usar a interface
inferior do Credential Manager para autenticação, adicione o atributo isCredential aos campos de nome de usuário
e senha. Isso impede que as caixas de diálogo de preenchimento automático (FillDialog e
SaveDialog) se sobreponham à interface da página inferior do Credential Manager.
O atributo isCredential é compatível com o Android 14 e versões mais recentes.
O exemplo a seguir mostra como adicionar o atributo isCredential
aos campos de nome de usuário e senha relevantes nas visualizações correspondentes do app:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isCredential="true" />
Próximas etapas
- Fazer login com chaves de acesso
- Gerenciar chaves de acesso
- Entenda os fluxos de experiência do usuário com chaves de acesso