In diesem Leitfaden wird die Implementierung der Verwendung von Passkeys zur Authentifizierung beschrieben. Bevor sich Ihre Nutzer mit Passkeys anmelden können, müssen Sie auch die Anleitung unter Passkeys erstellen befolgen.
Um sich mit einem Passkey zu authentifizieren, müssen Sie zuerst die Optionen abrufen, die zum Abrufen des öffentlichen Schlüssels von Ihrem App-Server erforderlich sind. Rufen Sie dann die Credential Manager API auf, um den öffentlichen Schlüssel abzurufen. Verarbeiten Sie dann die Anmeldeantwort entsprechend.
Übersicht
In diesem Leitfaden geht es hauptsächlich um die Änderungen, die in Ihrer Client-App erforderlich sind, damit sich Nutzer mit einem Passkey anmelden können. Außerdem wird die serverseitige Implementierung der App kurz beschrieben. Weitere Informationen zur serverseitigen Integration finden Sie unter Serverseitige Passkey-Authentifizierung.
So rufen Sie alle Passkey- und Passwortoptionen ab, die mit dem Konto des Nutzers verknüpft sind:
- Optionen für die Anforderung von Anmeldedaten vom Server abrufen: Senden Sie eine Anfrage von Ihrer App an Ihren Authentifizierungsserver, um den Prozess zur Anmeldung mit Passkey zu starten. Senden Sie vom Server aus die Optionen, die zum Abrufen der Anmeldedaten für den öffentlichen Schlüssel erforderlich sind, sowie eine eindeutige Challenge.
- Objekt erstellen, das zum Abrufen der Anmeldedaten für den öffentlichen Schlüssel erforderlich ist: Die vom Server gesendeten Optionen in ein
GetPublicKeyCredentialOption-Objekt einfügen - Optional: Bereiten Sie „getCredential“ vor: Unter Android 14 und höher können Sie die Latenz verringern, indem Sie die Kontoauswahl mit der Methode
prepareGetCredential()vor dem Aufrufen vongetCredential()anzeigen. - Anmeldevorgang starten: Rufen Sie die Methode
getCredential()auf, um den Nutzer anzumelden. - Antwort verarbeiten: Verarbeiten Sie jede der möglichen Anmeldedatenantworten.
- Ausnahmen behandeln: Achten Sie darauf, dass Sie Ausnahmen angemessen behandeln.
1. Optionen für Anmeldedatenanfragen vom Server abrufen
Fordern Sie vom Server die Optionen an, die zum Abrufen der Anmeldedaten für den öffentlichen Schlüssel erforderlich sind, sowie die challenge, die für jeden Anmeldeversuch eindeutig ist. Weitere Informationen zur serverseitigen Implementierung finden Sie unter Challenge erstellen und Optionen für Anmeldedatenanfragen erstellen.
Die Optionen sehen in etwa so aus:
{
"challenge": "<your app challenge>",
"allowCredentials": [],
"rpId": "<your app server domain>"
}
Weitere Informationen zu den Feldern finden Sie im Blogpost zur Anmeldung mit einem Passkey.
2. Das Objekt erstellen, das zum Abrufen der Anmeldedaten für den öffentlichen Schlüssel erforderlich ist
Verwenden Sie in Ihrer App die Optionen, um ein GetPublicKeyCredentialOption-Objekt zu erstellen.
Im folgenden Beispiel steht requestJson für die vom Server gesendeten Optionen.
// 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
)
Schließen Sie GetPublicKeyCredentialOption dann in ein GetCredentialRequest-Objekt ein.
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. Optional: Anmeldelatenz reduzieren
Unter Android 14 oder höher können Sie die Latenz beim Anzeigen der Kontoauswahl reduzieren, indem Sie die Methode prepareGetCredential() aufrufen, bevor Sie getCredential() aufrufen.
Die Methode prepareGetCredential() gibt ein PrepareGetCredentialResponse-Objekt zurück, das im Cache gespeichert wird. So kann mit der getCredential()-Methode im nächsten Schritt die Kontoauswahl mit den im Cache gespeicherten Daten aufgerufen werden.
coroutineScope {
val response = credentialManager.prepareGetCredential(
GetCredentialRequest(
listOf(
// Include all the sign-in options that your app supports
getPublicKeyCredentialOption,
getPasswordOption
)
)
)
}
4. Anmeldevorgang starten
Rufen Sie die Methode getCredential() auf, um dem Nutzer die Kontoauswahl zu präsentieren. Verwenden Sie das folgende Code-Snippet als Referenz dafür, wie der Anmeldevorgang gestartet wird:
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. Antwort verarbeiten
Verarbeiten Sie die Antwort, die einen von verschiedenen Typen von Berechtigungsnachweisobjekten enthalten kann.
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")
}
}
}
Das von der Authentifizierung zurückgegebene PublicKeyCredential ist im Wesentlichen eine signierte Assertion, die so strukturiert ist:
{
"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>"
}
}
Auf dem Server müssen Sie die Anmeldedaten bestätigen. Weitere Informationen finden Sie unter Nutzer bestätigen und anmelden.
6. Ausnahmen behandeln
Sie sollten alle Unterklassen-Ausnahmen von GetCredentialException verarbeiten.
Informationen zum Beheben der einzelnen Ausnahmen finden Sie in der Anleitung zur Fehlerbehebung.
coroutineScope {
try {
result = credentialManager.getCredential(
context = activityContext,
request = credentialRequest
)
} catch (e: GetCredentialException) {
Log.e("CredentialManager", "No credential available", e)
}
}