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 l'autenticazione con una passkey, devi prima recuperare le opzioni necessarie per recuperare la chiave pubblica dal tuo server delle app, quindi chiamare l'API Credential Manager per recuperare la chiave pubblica. Quindi, 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 scoprire 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: invia una richiesta dalla tua app al tuo 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: racchiudi 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 dell'account utilizzando il
metodo
prepareGetCredential()prima di chiamaregetCredential(). - Avvia il flusso di accesso: chiama il metodo
getCredential()per accedere all'utente - Gestisci la risposta: gestisci ciascuna delle possibili risposte delle credenziali.
- Gestisci eccezioni: assicurati di gestire le eccezioni in modo appropriato.
1. Ottenere le opzioni di richiesta delle credenziali dal server
Richiedi al server le opzioni necessarie per ottenere le credenziali della chiave pubblica,
nonché challenge, che è univoco per ogni tentativo di accesso. Per scoprire
di più sull'implementazione lato server, consulta Creare la
sfida e Creare opzioni di richiesta delle
credenziali.
Le opzioni sono simili alle seguenti:
{
"challenge": "<your app challenge>",
"allowCredentials": [],
"rpId": "<your app server domain>"
}
Per scoprire di più sui campi, consulta il post del blog sull'accesso con una passkey.
2. 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
)
Quindi, racchiudi 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
)
3. (Facoltativo) Ridurre la latenza di accesso
Su Android 14 o versioni successive, puoi ridurre la latenza quando mostri il selettore dell'account utilizzando il metodo prepareGetCredential() prima di chiamare getCredential().
Il metodo prepareGetCredential() restituisce un oggetto
PrepareGetCredentialResponse 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
)
)
)
}
4. Avviare il flusso di accesso
Chiama il metodo getCredential() per mostrare all'utente il selettore account. Utilizza lo snippet di codice
seguente come riferimento per avviare il flusso di accesso:
coroutineScope {
try {
result = credentialManager.getCredential(
// Use an activity-based context to avoid undefined system UI
// launching behavior.
context = activityContext,
request = credentialRequest
)
handleSignIn(result)
} catch (e: GetCredentialException) {
// Handle failure
}
}
5. Gestire la risposta
Gestisci la risposta, che può contenere uno dei vari tipi di oggetti delle 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")
}
}
}
Il PublicKeyCredential restituito 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ù, vedi Verificare e accedere all'utente.
6. Gestire le eccezioni
Devi gestire tutte le eccezioni delle sottoclassi 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)
}
}