Questa guida continua l'implementazione dell'utilizzo delle passkey per l'autenticazione. Prima che gli utenti possano accedere con le passkey, devi anche completare le istruzioni riportate in Creare passkey.
Per eseguire l'autenticazione con una passkey, devi prima recuperare le opzioni necessarie per recuperare la chiave pubblica dal server dell'app, quindi chiamare l'API Credential Manager per recuperare la chiave pubblica. Poi, gestisci la risposta di accesso in modo appropriato.
Panoramica
Questa guida si concentra sulle modifiche richieste nell'app client per consentire all'utente di accedere con una passkey e fornisce una breve panoramica dell'implementazione lato server dell'app. Per saperne di più sull'integrazione lato server, consulta Autenticazione con passkey lato server.
Per recuperare tutte le opzioni di passkey e password associate all'account dell'utente, completa questi passaggi:
- Recupera le opzioni di richiesta delle credenziali dal server: effettua una richiesta da lla tua app al server di autenticazione per avviare la procedura di accesso con passkey. Dal server, invia le opzioni necessarie per ottenere la credenziale della chiave pubblica, nonché una sfida univoca.
- Crea l'oggetto necessario per ottenere la credenziale della chiave pubblica: inserisci
le opzioni inviate dal server in un oggetto
GetPublicKeyCredentialOption. - (Facoltativo) **Prepara getCredential** : in Android 14 e versioni successive, puoi
ridurre la latenza mostrando il selettore account utilizzando il
prepareGetCredential()metodo prima di chiamaregetCredential(). - Avvia il flusso di accesso: chiama il metodo
getCredential()per consentire a ll'utente di accedere. - **Gestisci la risposta**: gestisci ciascuna delle possibili risposte delle credenziali.
- Gestisci le eccezioni: assicurati di gestire le eccezioni in modo appropriato.
Recupera le opzioni di richiesta delle credenziali dal server
Richiedi al server le opzioni necessarie per ottenere le credenziali della chiave pubblica, nonché la challenge, che è univoca per ogni tentativo di accesso. Per saperne
di più sull'implementazione lato server, consulta Creare la
challenge e Creare le opzioni di richiesta delle
credenziali.
Le opzioni sono simili alle seguenti:
{
"challenge": "<your app challenge>",
"allowCredentials": [],
"rpId": "<your app server domain>"
}
Per saperne di più sui campi, consulta il post del blog sull'accesso con una passkey.
Crea l'oggetto necessario per ottenere la credenziale della chiave pubblica
Nella tua app, utilizza le opzioni per creare un oggetto GetPublicKeyCredentialOption.
Nell'esempio seguente, requestJson rappresenta le opzioni inviate dal server.
// Get password logins from the credential provider on the user's device.
val getPasswordOption = GetPasswordOption()
// Get passkeys from the credential provider on the user's device.
val getPublicKeyCredentialOption = GetPublicKeyCredentialOption(
requestJson = requestJson
)
Poi, inserisci GetPublicKeyCredentialOption in un oggetto GetCredentialRequest.
val credentialRequest = GetCredentialRequest(
// Include all the sign-in options that your app supports.
listOf(getPasswordOption, getPublicKeyCredentialOption),
// Defines whether you prefer to use only immediately available
// credentials or hybrid credentials.
preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
)
(Facoltativo) Riduci la latenza di accesso
Su Android 14 o versioni successive, puoi ridurre la latenza quando mostri il selettore account
utilizzando il prepareGetCredential() metodo prima di chiamare
getCredential().
Il metodo prepareGetCredential() restituisce un
PrepareGetCredentialResponse oggetto memorizzato nella cache. In questo modo, il metodo getCredential() nel passaggio successivo visualizza il selettore account con i dati memorizzati nella cache.
coroutineScope {
val response = credentialManager.prepareGetCredential(
GetCredentialRequest(
listOf(
// Include all the sign-in options that your app supports
getPublicKeyCredentialOption,
getPasswordOption
)
)
)
}
Avvia il flusso di accesso
Chiama il metodo getCredential() per mostrare all'utente il selettore account. Utilizza il seguente snippet di codice come riferimento per avviare il flusso di accesso:
// Use an activity-based context to avoid undefined system UI
// launching behavior.
val context = MutableContextWrapper(activityContext)
coroutineScope {
try {
result = credentialManager.getCredential(
// Use MutableContextWrapper to avoid memory leak during configuration changes
context = context,
request = credentialRequest
)
handleSignIn(result)
} catch (e: GetCredentialException) {
// Handle failure
}
}
Gestisci la risposta
Gestisci la risposta, che può contenere uno dei vari tipi di oggetti credenziali.
fun handleSignIn(result: GetCredentialResponse) {
// Handle the successfully returned credential.
val credential = result.credential
when (credential) {
is PublicKeyCredential -> {
val responseJson = credential.authenticationResponseJson
// Share responseJson i.e. a GetCredentialResponse on your server to
// validate and authenticate
}
is PasswordCredential -> {
val username = credential.id
val password = credential.password
// Use id and password to send to your server to validate
// and authenticate
}
is CustomCredential -> {
// If you are also using any external sign-in libraries, parse them
// here with the utility functions provided.
if (credential.type == ExampleCustomCredential.TYPE) {
try {
val ExampleCustomCredential =
ExampleCustomCredential.createFrom(credential.data)
// Extract the required credentials and complete the authentication as per
// the federated sign in or any external sign in library flow
} catch (e: ExampleCustomCredential.ExampleCustomCredentialParsingException) {
// Unlikely to happen. If it does, you likely need to update the dependency
// version of your external sign-in library.
Log.e(TAG, "Failed to parse an ExampleCustomCredential", e)
}
} else {
// Catch any unrecognized custom credential type here.
Log.e(TAG, "Unexpected type of credential")
}
}
else -> {
// Catch any unrecognized credential type here.
Log.e(TAG, "Unexpected type of credential")
}
}
}
La PublicKeyCredential restituita dall'autenticazione è essenzialmente un'asserzione firmata, strutturata come segue:
{
"id": "<credential ID>",
"type": "public-key",
"rawId": "<raw credential ID>",
"response": {
"clientDataJSON": "<signed client data containing challenge>",
"authenticatorData": "<authenticator metadata>",
"signature": "<digital signature to be verified>",
"userHandle": "<user ID from credential registration>"
}
}
Sul server, devi verificare la credenziale. Per saperne di più, consulta Verificare e consentire l'accesso all'utente.
Gestisci le eccezioni
Devi gestire tutte le eccezioni di sottoclasse di GetCredentialException.
Per scoprire come gestire ogni eccezione, consulta la guida alla risoluzione dei problemi.
coroutineScope {
try {
result = credentialManager.getCredential(
context = activityContext,
request = credentialRequest
)
} catch (e: GetCredentialException) {
Log.e("CredentialManager", "No credential available", e)
}
}