Auf dieser Seite wird beschrieben, wie Sie einen Wiederherstellungsschlüssel erstellen, sich damit anmelden und ihn löschen.
Android-Kenntnisse
Auf GitHub ansehenAnmeldedaten wiederherstellen
android skills add restore-credentialsVersionskompatibilität
Die Funktion zur Wiederherstellung von Anmeldedaten des Credential Managers funktioniert auf Geräten mit Android 9 (API-Level 28) und höher, Google Play-Diensten (GMS) Core-Version 242200000 (v24.22) oder höher und Version 1.5.0 oder höher der androidx.credentials-Bibliothek. Auf Geräten ohne Google Play-Dienste oder mit einer älteren GMS-Version solltest du CreateCredentialProviderConfigurationException und GetCredentialProviderConfigurationException abfangen, damit deine App ordnungsgemäß auf die Standardanmeldung zurückgreift.
Vorbereitung
Konfiguriere einen WebAuthn-Server für vertrauende Seiten, der dem Server für Passkeys ähnelt. Wenn Sie bereits einen Server für die Authentifizierung mit Passkeys eingerichtet haben, können Sie dieselben WebAuthn-Registrierungs- und Assertion-Endpunkte für Wiederherstellungsschlüssel verwenden.
Abhängigkeiten
Fügen Sie der Datei build.gradle Ihres App-Moduls die folgenden Abhängigkeiten hinzu:
Kotlin
dependencies { implementation("androidx.credentials:credentials:1.7.0-alpha02") implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha02") }
Groovy
dependencies { implementation "androidx.credentials:credentials:1.7.0-alpha02" implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02" }
Die Funktion zur Wiederherstellung von Anmeldedaten ist ab Version 1.5.0 der androidx.credentials-Bibliothek verfügbar. Es wird jedoch empfohlen, nach Möglichkeit die neuesten stabilen Versionen der Abhängigkeiten zu verwenden.
Auswirkungen von android:allowBackup auf die Wiederherstellung von Anmeldedaten
Das Manifestattribut android:allowBackup steuert die Sicherung von App-Daten, die auf drei verschiedene Arten mit der Wiederherstellung von Anmeldedaten interagiert:
- Schlüsselübertragung wiederherstellen (unabhängig von
allowBackup): Die Google Play-Dienste übertragen dasRestoreCredential-Schlüsselpaar mithilfe einer Ende-zu-Ende-verschlüsselten Cloud-Sicherung oder einer lokalen Übertragung von Gerät zu Gerät (D2D), unabhängig davon, obandroid:allowBackuptrueoderfalseist. Bei der Übertragung von Gerät zu Gerät wird der Wiederherstellungsschlüssel immer übertragen. Die einzige Ausnahme ist, wenn der Nutzer die Cloud-Sicherung in den Android-Einstellungen deaktiviert hat. - Hintergrundwiederherstellung in
BackupAgent(erfordertandroid:allowBackup="true"): Die automatische Anmeldung im Hintergrund, bevor der Nutzer die App auf dem neuen Gerät öffnet (BackupAgent.onRestoreFinished()), wird nur ausgeführt, wennandroid:allowBackup="true"undandroid:backupAgentin Ihrem Manifest konfiguriert sind. Wennandroid:allowBackup="false", stelle die Sitzung wieder her, wenn der Nutzer deine Haupt-Activityzum ersten Mal startet. Sie können auch beide Ansätze implementieren, um die Wiederherstellung robuster zu machen. - Android Studio Cloud Backup-Tests (erfordert
android:allowBackup="true"): Zum Testen des Sicherungstyps Cloud im Sicherungs- und Wiederherstellungstool von Android Studio istandroid:allowBackup="true"erforderlich. Gerät-zu-Gerät-Tests funktionieren dagegen unabhängig vonallowBackup.
Übersicht
Die Wiederherstellung von Anmeldedaten folgt einem dreistufigen Lebenszyklus auf den vorherigen und neuen Geräten der Nutzer:
- Wiederherstellungsschlüssel auf dem vorherigen Gerät erstellen: Nachdem sich der Nutzer angemeldet hat (oder beim Start der App, wenn der Nutzer bereits angemeldet ist und kein Wiederherstellungsschlüssel im lokalen Speicher aufgezeichnet ist), rufen Sie die Erstellungsoptionen von Ihrem Relying-Party-Server ab und rufen Sie
credentialManager.createCredential()auf. - Mit dem Wiederherstellungsschlüssel auf dem neuen Gerät anmelden: Rufe den übertragenen
RestoreCredentialmit einer zweistufigen Strategie ab: zuerst im Hintergrund inBackupAgent.onRestoreFinished()(wennandroid:allowBackup="true"), damit die Hintergrundsynchronisierung und Push-Benachrichtigungen sofort fortgesetzt werden, und dann als Fallback in deinem LauncherActivity.onCreate()beim ersten App-Start. - Wiederherstellungsschlüssel bei der Abmeldung löschen: Wenn sich der Nutzer abmeldet oder seine Sitzung vom Server ungültig gemacht wird, rufen Sie
credentialManager.clearCredentialState()mitClearCredentialStateRequest(ClearCredentialStateRequest.TYPE_CLEAR_RESTORE_CREDENTIAL)auf und löschen Sie das lokale Synchronisierungs-Flag.
Wiederherstellungsschlüssel erstellen
Ihre App sollte alle Fälle abdecken, in denen sich ein Nutzer anmeldet, damit für aktive Nutzer ein Wiederherstellungsschlüssel erstellt wird. Erstellen Sie den Wiederherstellungsschlüssel in den folgenden Szenarien:
- Wenn der Nutzer angemeldet ist und noch kein Wiederherstellungsschlüssel erstellt wurde (z. B. in der Methode
onCreate()für die Haupt-Activity). - Wenn sich der Nutzer anmeldet oder ein neues Konto registriert.
Damit createCredential() nicht bei jedem App-Start aufgerufen wird, speichern Sie ein lokales Synchronisierungs-Flag wie has_synced_restore_credential im lokalen Speicher. Speichern Sie dieses Flag nicht in standardmäßig gesicherten SharedPreferences- oder DataStore-Dateien, es sei denn, diese Datei ist in data_extraction_rules.xml ausgeschlossen. Andernfalls kopiert die automatische Sicherung has_synced_restore_credential = true auf das neue Gerät und verhindert, dass das neue Gerät einen eigenen Wiederherstellungsschlüssel generiert oder rotiert.
Credential Manager instanziieren
Verwenden Sie den Aktivitätskontext Ihrer App, um ein CredentialManager-Objekt zu instanziieren.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)
Optionen zum Erstellen von Anmeldedaten vom Anwendungsserver abrufen
Verwenden Sie eine FIDO-konforme Bibliothek auf Ihrem Anwendungsserver, um Ihrer Client-App die PublicKeyCredentialCreationOptions-JSON-Datei zu senden, die zum Erstellen der Wiederherstellungs-Anmeldedaten erforderlich ist. Weitere Informationen zur serverseitigen Implementierung finden Sie im Leitfaden für die serverseitige Implementierung.
Die JSON-Datei mit den Erstellungsoptionen hat dieselbe Struktur wie die Passkey-Registrierung:
{
"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"
}
}
Achten Sie darauf, dass das JSON-Objekt für die Erstellungsoptionen die folgenden Anforderungen erfüllt:
challengeunduser.id: Codieren Sie beide Werte als Base64URL-Strings ohne Padding. Ersetzen Sie dabei+durch-und/durch_und entfernen Sie nachfolgende=. Standard-Base64-Zeichen oder Roh-Integer-IDs führen zuCreateRestoreCredentialDomExceptionoderIllegalArgumentException.rp.id: Legen Sie hier die Domain Ihrer vertrauenden Partei fest (z. B.example.com).pubKeyCredParams: Schließen Sie{"type": "public-key", "alg": -7}(ES256) und{"type": "public-key", "alg": -257}(RS256) ein.
Wiederherstellungsschlüssel erstellen
Nachdem Sie die JSON-Datei mit den Optionen für die Erstellung des öffentlichen Schlüssels von Ihrem Server erhalten haben, verpacken Sie die JSON-Datei in ein CreateRestoreCredentialRequest-Objekt und rufen Sie createCredential() für das CredentialManager-Objekt auf.
// createRestoreRequest contains the details sent by the server
val response = credentialManager.createCredential(context, createRestoreRequest)
Wichtige Punkte zum Code
Das Objekt
CreateRestoreCredentialRequestenthält die folgenden Felder:requestJson: Die Optionen für die Erstellung von Anmeldedaten, die vom Anwendungsserver im Format der Web Authentication API fürPublicKeyCredentialCreationOptionsJSONgesendet werden.isCloudBackupEnabled: FeldBoolean, um festzulegen, ob der Wiederherstellungsschlüssel in der Cloud gesichert werden soll. Standardmäßig ist dieses Flagtrue. Dieses Feld hat die folgenden Werte:true: (Empfohlen) Mit diesem Wert wird die Sicherung von Wiederherstellungsschlüsseln in der Cloud aktiviert, wenn der Nutzer Google Backup und die Ende-zu-Ende-Verschlüsselung, z. B. eine Displaysperre, aktiviert hat.false: Mit diesem Wert wird der Schlüssel lokal und nicht in der Cloud gespeichert. Der Schlüssel ist auf dem neuen Gerät nicht verfügbar, wenn der Nutzer die Wiederherstellung aus der Cloud auswählt. Er wird jedoch bei einer lokalen Kabel- oder WLAN-Geräte-zu-Geräte-Einrichtung (D2D) übertragen.
Antwort auf die Erstellung von Anmeldedaten verarbeiten
Die Credential Manager API gibt eine Antwort vom Typ CreateRestoreCredentialResponse zurück. Diese Antwort enthält die Antwort auf die Registrierung der Anmeldedaten für den öffentlichen Schlüssel im JSON-Format.
Sende response.registrationResponseJson von deiner App an den Server der vertrauenden Seite, um den öffentlichen Schlüssel zu überprüfen und im Konto des Nutzers zu speichern. Speichere dann die lokale Synchronisierungsmarkierung im lokalen Speicher. Weitere Informationen zur serverseitigen Überprüfung finden Sie im Leitfaden für Passkeys.
Behandeln Sie während der Erstellung des Wiederherstellungsschlüssels die folgenden Ausnahmen:
CreateRestoreCredentialDomException: Diese Ausnahme tritt auf, wennrequestJsonungültig ist und nicht dem WebAuthn-Format fürPublicKeyCredentialCreationOptionsJSONentspricht.E2eeUnavailableException: Diese Ausnahme tritt auf, wennisCloudBackupEnabledden Werttruehat, das Gerät des Nutzers aber keine Datensicherung oder Ende-zu-Ende-Verschlüsselung wie eine Displaysperre hat.
Damit Anmeldedaten für die Wiederherstellung für lokale Übertragungen von Gerät zu Gerät (D2D) erstellt werden, auch wenn die Cloud-Ende-zu-Ende-Verschlüsselung nicht verfügbar ist, fangen SieE2eeUnavailableExceptionab und wiederholen SiecreateCredential()sofort mitCreateRestoreCredentialRequest(requestJson, isCloudBackupEnabled = false).IllegalArgumentException: Diese Ausnahme tritt auf, wennrequestJsonleer ist, kein gültiges JSON-Format hat oder keine gültige Base64URL-codierteuser.identhält, die den WebAuthn-Spezifikationen entspricht.
Mit einem Wiederherstellungsschlüssel anmelden
Verwenden Sie die Wiederherstellung von Anmeldedaten, um den Nutzer während der Geräteeinrichtung im Hintergrund anzumelden.
Optionen zum Abrufen von Anmeldedaten vom Anwendungsserver abrufen
Bevor Sie getCredential() auf dem neuen Gerät aufrufen, fordern Sie von Ihrem App-Server eine WebAuthn-PublicKeyCredentialRequestOptions-JSON-Challenge an. Da die App auf dem neuen Gerät noch nicht weiß, welcher Nutzer sich anmeldet, muss dieser Endpunkt nicht authentifiziert sein (nutzerlose Erkennung). Informationen zu Servern finden Sie unter Mit einem Passkey anmelden und im Leitfaden zur serverseitigen Authentifizierung.
Das JSON-Objekt für die Abrufoptionen hat die folgende Struktur:
{
"challenge": "<your app challenge>",
"allowCredentials": [],
"rpId": "<your app server domain>"
}
Konfigurieren Sie die JSON-Datei mit den Abrufoptionen auf Ihrem Server so:
allowCredentials: Lassen Sie dieses Feld weg oder übergeben Sie ein leeres Array ([]), da das Konto des Nutzers vor der Wiederherstellung nicht bekannt ist. NachdemgetCredential()zurückgegeben wurde, identifiziert Ihr Server den Nutzer anhand des Feldsresponse.userHandle(das mit der bei der Erstellung registriertenuser.idübereinstimmt) und sucht den öffentlichen Schlüssel anhand vonid(credentialId).userVerification: Auf"discouraged"(oder"preferred") festgelegt. Da „Anmeldedaten wiederherstellen“ im Hintergrund ohne biometrische oder Displaysperre-UI ausgeführt wird, überschreibt Android"required"mit"discouraged"und die an Ihren Server zurückgegebenen Authentifikatordaten haben das Flag „Nutzer verifiziert“ (uv) auffalsefestgelegt. Konfigurieren Sie den WebAuthn-Serverprüfer so, dass eruv = falsefür Bestätigungen des Wiederherstellungsschlüssels akzeptiert.
Wiederherstellungsschlüssel abrufen
Wenn du den Wiederherstellungsschlüssel auf dem neuen Gerät abrufen möchtest, verpacke den requestJson des Servers in einem GetRestoreCredentialOption innerhalb eines GetCredentialRequest und rufe getCredential() für das CredentialManager-Objekt auf.
Implementiere eine zweistufige Wiederherstellungsstrategie, damit Nutzer angemeldet sind, unabhängig davon, ob die Wiederherstellung von App-Daten im Hintergrund ausgeführt wird oder nicht:
- Stufe 1 (Wiederherstellung im Hintergrund in
BackupAgent.onRestoreFinished()): Wenn die Sicherung von App-Daten aktiviert ist (android:allowBackup="true"), erstelle eine abgeleitete Klasse vonBackupAgentund überschreibeonRestoreFinished(). Verwende nichtonRestore(), da dies nur für Legacy-Schlüssel/Wert-Sicherungen aufgerufen wird. DaonRestoreFinished()synchron undgetCredential()eine Kotlin-suspend-Funktion ist, müssen Sie den Aufruf mitrunBlocking(Dispatchers.IO)überbrücken.NoCredentialExceptionwird im Hintergrund abgefangen, wenn kein Wiederherstellungsschlüssel vorhanden ist. - Stufe 2 (Vordergrund-Fallback im Launcher
Activity.onCreate()): Rufe beim ersten Start der App, wenn keine lokale Sitzung vorhanden ist,getCredential()auslifecycleScopeauf, bevor der Anmeldebildschirm angezeigt wird. Dadurch werden Apps mitandroid:allowBackup="false"verarbeitet und wiederhergestellt, wenn das Gerät offline war, alsonRestoreFinished()ausgeführt wurde.
Wenn du einer App, die bereits die automatische Sicherung mit android:allowBackup="true" verwendet, ein neues BackupAgent hinzufügst, musst du auch android:fullBackupOnly="true" für das <application>-Element in AndroidManifest.xml festlegen, damit Android weiterhin die automatische Sicherung verwendet, anstatt zur alten Schlüssel/Wert-Sicherung zu wechseln.
// Fetch the options required to get the restore key
val authenticationJson = fetchAuthenticationJson()
// Create the GetRestoreCredentialRequest object
val options = GetRestoreCredentialOption(authenticationJson)
val getRequest = GetCredentialRequest(listOf(options))
val response = credentialManager.getCredential(context, getRequest)
// Type-check and extract the restore credential
val credential = response.credential as RestoreCredential
Die Credential Manager API gibt ein GetCredentialResponse zurück, dessen credential-Attribut ein RestoreCredential (kein PublicKeyCredential) ist, das authenticationResponseJson enthält.
Anmeldeantwort verarbeiten
Senden Sie restoreCredential.authenticationResponseJson von der App an den Server der vertrauenden Seite, um die kryptografische Assertion zu prüfen und ein neues Sitzungstoken für den Nutzer auszustellen. Weitere Informationen zur serverseitigen Überprüfung finden Sie unter Mit einem Passkey anmelden.
Beachten Sie beim Entwerfen des Backend-Speichers und der Lebenszyklusrichtlinien für Wiederherstellungsschlüssel die folgenden Richtlinien:
- Wiederherstellungsschlüssel von Nutzer-Passkeys unterscheiden: Taggen Sie Wiederherstellungsschlüssel in Ihrer Datenbank, damit sie auf den für Nutzer sichtbaren Bildschirmen zur Passkey-Verwaltung ausgeblendet und von der Nutzerbestätigung (
uv = true) ausgenommen werden. - Unterstützung mehrerer aktiver Geräte pro Nutzer: Ein Nutzer kann mehrere Geräte haben (z. B. ein Smartphone und ein Tablet). Lassen Sie mehrere aktive Wiederherstellungsschlüssel pro Nutzerkonto zu (z. B. nach Geräte- oder Installations-ID), anstatt eine einzelne Zeile zu überschreiben.
- Legen Sie eine geeignete TTL fest und bereinigen Sie verwaiste Schlüssel: Wenn Sie eine App deinstallieren oder App-Daten löschen, wird der lokale Wiederherstellungsschlüssel gelöscht, ohne dass Ihr Server benachrichtigt wird. Bewahren Sie Wiederherstellungsschlüssel lange genug auf, um Geräte-Upgrade-Zeitfenster zu überstehen (auch wenn sich der Nutzer nach der Übertragung auf dem alten Gerät abmeldet), und entfernen Sie veraltete Schlüssel basierend auf der Inaktivitäts-TTL oder den Schlüssellimits pro Nutzer.
Wiederherstellungsschlüssel löschen
Der Credential Manager ist zustandslos und hat keine Informationen über Nutzeraktivitäten. Daher werden Wiederherstellungsschlüssel nach der Verwendung nicht automatisch gelöscht. Rufen Sie zum Löschen eines Wiederherstellungsschlüssels die Methode clearCredentialState() auf. Löschen Sie den Schlüssel aus Sicherheitsgründen, wenn sich ein Nutzer abmeldet, damit er beim nächsten Start der App nicht automatisch wieder angemeldet wird.
Wiederherstellungsschlüssel werden nur in den folgenden Situationen entfernt:
- Aktionen auf Systemebene: Nutzer deinstallieren die App oder löschen ihre Daten.
- Aufrufe auf App-Ebene: Löschen Sie den Schlüssel programmatisch, indem Sie
clearCredentialState()aufrufen, wenn Sie die Abmeldung des Nutzers im Code Ihrer App verarbeiten.
Da bei einem standardmäßigen ClearCredentialStateRequest() nur der Standard-Sitzungsstatus gelöscht wird und der Wiederherstellungsschlüssel intakt bleibt, sollten Sie beim Abmelden einen doppelten Löschvorgang durchführen:
- Rufen Sie
credentialManager.clearCredentialState(ClearCredentialStateRequest())auf, um den Sitzungsstatus des aktiven Anbieters von Anmeldedaten zu löschen. - Rufen Sie
credentialManager.clearCredentialState()mitClearCredentialStateRequest(ClearCredentialStateRequest.TYPE_CLEAR_RESTORE_CREDENTIAL)auf, um die gespeicherteRestoreCredentialzu löschen. - Löschen Sie die lokale
has_synced_restore_credential-Markierung aus dem lokalen Speicher.
// Create a ClearCredentialStateRequest object
val clearRequest = ClearCredentialStateRequest(TYPE_CLEAR_RESTORE_CREDENTIAL)
// When the user logs out, delete the restore key
val response = credentialManager.clearCredentialState(clearRequest)
Nächste Schritte
- Wiederherstellung von Anmeldedaten testen: Testen Sie die Wiederherstellungsabläufe in der Cloud und zwischen Geräten mit Android Studio oder
adb shell bmgr. - Automatisierte Sicherungs- und Wiederherstellungstests: Schreiben Sie JUnit 5-Hosttests mit
BackupRestoreController, umCLOUD_ENCRYPTED- undDEVICE_TO_DEVICE-Wiederherstellungen in CI zu überprüfen.