Revision 2025 Q4: Auth-Abläufe mit der Credential Manager API in Ihrer Android-App vereinfachen

1. Hinweis

Herkömmliche Authentifizierungslösungen bergen eine Reihe von Sicherheits- und Nutzerfreundlichkeitsproblemen.

Passwörter sind weit verbreitet, aber…

  • Leicht zu vergessen
  • Nutzer müssen wissen, wie sie starke Passwörter erstellen.
  • Angreifer können sie leicht abfangen, sammeln und wiedergeben.

Android hat die Credential Manager API entwickelt, um die Anmeldung zu vereinfachen und Sicherheitsrisiken zu minimieren. Dazu werden Passkeys unterstützt, der Branchenstandard der nächsten Generation für die passwortlose Authentifizierung.

Credential Manager unterstützt Passkeys und kombiniert sie mit herkömmlichen Authentifizierungsmethoden wie Passwörtern und „Über Google anmelden“.

Nutzer können Passkeys erstellen und im Google Passwortmanager speichern. Diese Passkeys werden dann auf allen Android-Geräten synchronisiert, auf denen der Nutzer angemeldet ist. Bevor sich ein Nutzer mit einem Passkey anmelden kann, muss ein Passkey erstellt, einem Nutzerkonto zugeordnet und sein öffentlicher Schlüssel auf einem Server gespeichert werden.

In diesem Codelab erfahren Sie, wie Sie sich mit der Credential Manager API mit Passkeys und Passwörtern registrieren und diese für die zukünftige Authentifizierung verwenden. Es gibt zwei Abläufe:

  • Registrierung : mit Passkeys und Passwort.
  • Anmelden : mit Passkeys und gespeicherten Passwörtern.

Vorbereitung

  • Grundlegende Kenntnisse zum Ausführen von Apps in Android Studio
  • Grundlegendes Verständnis des Authentifizierungsablaufs in Android-Apps.
  • Grundlegendes Verständnis von Passkeys

Lerninhalte

  • So erstellen Sie einen Passkey.
  • So speichern Sie Passwörter in einem Passwortmanager.
  • So authentifizieren Sie Nutzer mit einem Passkey oder einem gespeicherten Passwort.

Voraussetzungen

Eine der folgenden Gerätekonfigurationen:

  • Ein Android-Gerät mit Android 9 oder höher (für Passkeys) und Android 4.4 oder höher(für die Passwortauthentifizierung über die Credential Manager API).
  • Gerät vorzugsweise mit biometrischem Sensor.
  • Registrieren Sie eine Displaysperre (biometrisch oder anderweitig).
  • Kotlin-Plug-in-Version : 1.8.10

2. Einrichten

Für diese Beispiel-App ist eine Verknüpfung digitaler Assets mit einer Website erforderlich, damit Credential Manager die Verknüpfung validieren und fortfahren kann. Die in den Mock-Antworten verwendete RP-ID stammt daher von einem simulierten Drittanbieter-Server. Wenn Sie eine eigene Mock-Antwort ausprobieren möchten, fügen Sie Ihre App-Domain hinzu und vergessen Sie nicht, die Verknüpfung digitaler Assets wie hier beschrieben abzuschließen.

Verwenden Sie denselben debug.keystore, der im Projekt erwähnt wird, um Debug- und Release-Varianten zu erstellen und die Digital Asset Linking des Paketnamens und des SHA auf Ihrem Mock-Server zu überprüfen. (Das wird für die Beispiel-App in build.gradle bereits für Sie erledigt.)

  1. Klonen Sie dieses Repository auf Ihrem Laptop über den Branch credman_codelab: https://github.com/android/identity-samples/tree/credman_codelab
git clone -b credman_codelab https://github.com/android/identity-samples.git
  1. Rufen Sie das Modul CredentialManager auf und öffnen Sie das Projekt in Android Studio.

Sehen wir uns den Ausgangsstatus der App an.

So sehen Sie, wie der ursprüngliche Zustand der App funktioniert:

  1. Starten Sie die App.
  2. Sie sehen einen Hauptbildschirm mit Schaltflächen zum Registrieren und Anmelden. Diese Schaltflächen haben noch keine Funktion, aber wir werden sie in den nächsten Abschnitten aktivieren.

7a6fe80f4cf877a8.jpeg

3. Möglichkeit zur Registrierung mit Passkeys hinzufügen

Wenn sich Nutzer für ein neues Konto in einer Android-App registrieren, die die Credential Manager API verwendet, können sie einen Passkey für ihr Konto erstellen. Dieser Passkey wird sicher beim ausgewählten Anmeldedatenanbieter des Nutzers gespeichert und für zukünftige Anmeldungen verwendet, ohne dass der Nutzer jedes Mal sein Passwort eingeben muss.

Als Nächstes erstellen Sie einen Passkey und registrieren Nutzeranmeldedaten mithilfe von Biometrie/Displaysperre.

Mit Passkey registrieren

Der Code in CredentialManager/app/src/main/java/com/google/credentialmanager/sample/SignUpScreen.kt definiert das Textfeld „username“ und eine Schaltfläche zum Registrieren mit einem Passkey.

1f4c50daa2551f1.jpeg

Lambda „createCredential()“ zur Verwendung in Ansichtsmodellen definieren

Für Credential Manager-Objekte muss ein Activity übergeben werden, das mit einem Screen verknüpft ist. Credential Manager-Vorgänge werden jedoch in der Regel in View-Modellen ausgelöst. Es wird nicht empfohlen, in View-Modellen auf Aktivitäten zu verweisen. Daher definieren wir Credential Manager-Funktionen in einer separaten Datei CredentialManagerUtil.kt und verweisen in den entsprechenden Screens darauf. Diese übergeben sie dann als Callbacks über Lambda-Funktionen an ihre ViewModels.

Suchen Sie in der Funktion createCredential() in CredentialManagerUtil.kt nach dem Kommentar TODO und rufen Sie die Funktion CredentialManager.create() auf:

CredentialManagerUtil.kt

suspend fun createCredential(
    activity: Activity,
    request: CreateCredentialRequest
): CreateCredentialResponse {
    TODO("Create a CredentialManager object and call createCredential() with a CreateCredentialRequest")
    val credentialManager = CredentialManager.create(activity)
    return credentialManager.createCredential(activity, request)
}

Übergeben Sie die Challenge und andere JSON-Antworten an einen createPasskey()-Aufruf.

Bevor ein Passkey erstellt wird, müssen Sie vom Server die erforderlichen Informationen anfordern, die während des createCredential()-Aufrufs an die Credential Manager API übergeben werden.

Sie haben bereits eine Mock-Antwort in den Assets Ihres Projekts mit dem Namen RegFromServer.txt, die die erforderlichen Parameter in diesem Codelab zurückgibt.

  • Rufen Sie in Ihrer App SignUpViewModel.kt auf und suchen Sie nach der Methode signUpWithPasskeys, in der Sie die Logik zum Erstellen eines Passkeys und zum Anmelden des Nutzers schreiben. Sie finden die Methode in derselben Klasse.
  • Suchen Sie den Kommentarblock TODO bis create a CreatePublicKeyCredentialRequest() und ersetzen Sie ihn durch den folgenden Code:

SignUpViewModel.kt

TODO("Create a CreatePublicKeyCredentialRequest() with necessary registration json from server")
    val request = CreatePublicKeyCredentialRequest(
        jsonProvider.fetchRegistrationJson()
            .replace("<userId>", getEncodedUserId())
            .replace("<userName>", _username.value)
            .replace("<userDisplayName>", _username.value)
            .replace("<challenge>", getEncodedChallenge())
    )

Die Methode jsonProvider.fetchRegistrationJsonFromServer() liest eine emulierte Server-PublicKeyCredentialCreationOptions-JSON-Antwort aus Assets und gibt die Registrierungs-JSON zurück, die beim Erstellen des Passkeys übergeben werden soll. Wir ersetzen einige der Platzhalterwerte durch Nutzereingaben aus unserer App und einige simulierte Felder:

  • Dieses JSON ist unvollständig und enthält vier Felder, die ersetzt werden müssen.
  • Die UserId muss eindeutig sein, damit ein Nutzer bei Bedarf mehrere Passkeys erstellen kann. Ersetzen Sie <userId> durch den generierten userId-Wert.
  • <challenge> muss auch eindeutig sein. Sie generieren also eine zufällige, eindeutige Challenge. Die Methode ist bereits in Ihrem Code enthalten.

Eine Antwort von einem echten Server PublicKeyCredentialCreationOptions kann mehr Optionen zurückgeben. Ein Beispiel für einige dieser Felder ist unten zu sehen:

{
  "challenge": String,
  "rp": {
    "name": String,
    "id": String
  },
  "user": {
    "id": String,
    "name": String,
    "displayName": String
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    }
  ],
  "timeout": 1800000,
  "attestation": "none",
  "excludeCredentials": [],
  "authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}

In der folgenden Tabelle werden einige der wichtigen Parameter in einem PublicKeyCredentialCreationOptions-Objekt erläutert:

Parameter

Textzeilen

challenge

Ein vom Server generierter zufälliger String, der genügend Entropie enthält, um das Erraten unmöglich zu machen. Es sollte mindestens 16 Byte lang sein. Dies ist erforderlich, wird aber bei der Registrierung nicht verwendet, es sei denn, es wird eine Attestierung durchgeführt.

user.id

Die eindeutige ID eines Nutzers. Dieser Wert darf keine personenidentifizierbaren Informationen wie E‑Mail-Adressen oder Nutzernamen enthalten. Ein zufälliger 16-Byte-Wert, der pro Konto generiert wird, ist gut geeignet.

user.name

Dieses Feld sollte eine eindeutige Kennung für das Konto enthalten, die der Nutzer kennt, z. B. seine E‑Mail-Adresse oder seinen Nutzernamen. Diese wird in der Kontoauswahl angezeigt. Wenn Sie einen Nutzernamen verwenden, geben Sie denselben Wert wie bei der Passwortauthentifizierung ein.

user.displayName

Dieses Feld ist ein optionaler, nutzerfreundlicherer Name für das Konto.

rp.id

Die Relying Party-Entität entspricht den Details Ihrer Anwendung. Es hat die folgenden Attribute:

  • name (erforderlich): der Name Ihrer Anwendung
  • ID (optional): Entspricht der Domain oder Subdomain. Wenn nicht vorhanden, wird die aktuelle Domain verwendet.
  • icon (optional).

pubKeyCredParams

Liste der zulässigen Algorithmen und Schlüsseltypen. Diese Liste muss mindestens ein Element enthalten.

excludeCredentials

Der Nutzer, der versucht, ein Gerät zu registrieren, hat möglicherweise bereits andere Geräte registriert. Wenn Sie die Erstellung mehrerer Anmeldedaten für dasselbe Konto auf einem einzelnen Authenticator einschränken möchten, können Sie diese Geräte ignorieren. Das transports-Element sollte, sofern angegeben, das Ergebnis des Aufrufs von getTransports() während der Registrierung der einzelnen Anmeldedaten enthalten.

authenticatorSelection.authenticatorAttachment

Gibt an, ob das Gerät an der Plattform angebracht werden soll oder nicht oder ob dies nicht erforderlich ist. Legen Sie diesen Wert auf platform fest. Das bedeutet, dass Sie einen Authenticator wünschen, der in das Plattformgerät eingebettet ist. Der Nutzer wird nicht aufgefordert, z. B. einen USB-Sicherheitsschlüssel einzuführen.

residentKey

Geben Sie den Wert required an, um einen Passkey zu erstellen.

Anmeldedaten erstellen

  1. Nachdem Sie ein CreatePublicKeyCredentialRequest() erstellt haben, müssen Sie den createCredential()-Aufruf mit der erstellten Anfrage aufrufen.

SignUpViewModel.kt

try {
   TODO("Call createCredential() with createPublicKeyCredentialRequest")
   createCredential(request)
   TODO("Complete the registration process after sending public key credential to your server and let the user in")

} catch (e: CreateCredentialException) {
   handlePasskeyFailure(e)
}

  • Sie legen die Sichtbarkeit der gerenderten Ansichten fest und behandeln die Ausnahmen, wenn die Anfrage aus irgendeinem Grund fehlschlägt oder nicht erfolgreich ist. Hier werden die Fehlermeldungen protokolliert und in einem Fehlerdialogfeld in der App angezeigt. Die vollständigen Fehlerlogs können Sie in Android Studio oder mit dem Befehl adb debug aufrufen.

1ea8ace66135de1e.png

  1. Schließlich müssen Sie die Registrierung abschließen. Die App sendet Anmeldedaten für den öffentlichen Schlüssel an den Server, der sie für den aktuellen Nutzer registriert.

Hier haben wir einen Mock-Server verwendet. Wir geben also einfach „true“ zurück, um anzugeben, dass der Server den registrierten öffentlichen Schlüssel für zukünftige Authentifizierungs- und Validierungszwecke gespeichert hat. Weitere Informationen zur serverseitigen Passkey-Registrierung

Suchen Sie in der Methode signUpWithPasskeys() nach dem relevanten Kommentar und ersetzen Sie ihn durch den folgenden Code:

SignUpViewModel.kt

try {
    createCredential(request)
    TODO("Complete the registration process after sending public key credential to your server and let the user in")
registerResponse()
    DataProvider.setSignedInThroughPasskeys(true)
    _navigationEvent.emit(NavigationEvent.NavigateToHome(signedInWithPasskeys = true))
} catch (e: CreateCredentialException) {
   handlePasskeyFailure(e)
}
  • registerResponse() gibt true zurück, was darauf hinweist, dass der Mock-Server den öffentlichen Schlüssel zur zukünftigen Verwendung gespeichert hat.
  • Setzen Sie das Flag setSignedInThroughPasskeys auf true.
  • Nach der Anmeldung leiten Sie den Nutzer zum Startbildschirm weiter.

Ein echtes PublicKeyCredential kann weitere Felder enthalten. Ein Beispiel für diese Felder ist unten zu sehen:

{
  "id": String,
  "rawId": String,
  "type": "public-key",
  "response": {
    "clientDataJSON": String,
    "attestationObject": String,
  }
}

In der folgenden Tabelle werden einige der wichtigen Parameter in einem PublicKeyCredential-Objekt erläutert:

Parameter

Textzeilen

id

Eine Base64URL-codierte ID des erstellten Passkeys. Anhand dieser ID kann der Browser bei der Authentifizierung feststellen, ob ein passender Passkey auf dem Gerät vorhanden ist. Dieser Wert muss in der Datenbank im Backend gespeichert werden.

rawId

Eine ArrayBuffer-Objektversion der Anmeldedaten-ID.

response.clientDataJSON

Ein ArrayBuffer-Objekt mit codierten Clientdaten.

response.attestationObject

Ein ArrayBuffer-codiertes Attestierungsobjekt. Es enthält wichtige Informationen wie eine RP‑ID, Flags und einen öffentlichen Schlüssel.

Führen Sie die App aus. Sie können dann auf die Schaltfläche Mit Passkeys registrieren klicken und einen Passkey erstellen.

4. Passwort im Anmeldedatenanbieter speichern

In dieser App ist auf dem Registrierungsbildschirm bereits eine Registrierung mit Nutzername und Passwort implementiert.

Wenn Sie die Anmeldedaten für das Nutzerpasswort bei ihrem Passwortanbieter speichern möchten, implementieren Sie eine CreatePasswordRequest, die an createCredential() übergeben wird, um das Passwort zu speichern.

  • Suchen Sie die Methode signUpWithPassword() und ersetzen Sie das TODO durch einen createPassword-Aufruf:

SignUpViewModel.kt

TODO("CreatePasswordRequest with entered username and password")