Credential Manager: Passkeys und Passwörter vereint
Credential Manager bündelt Passkeys, Passwörter und föderierte Anmeldungen in einer API. Die Integration vereinfacht sichere Authentifizierung in Android-Apps.
Sichere Authentifizierung war lange ein Flickenteppich aus proprietären SDKs, eigenen Passwort-Dialogen und halbgaren Passwort-Manager-Integrationen. Mit dem Credential Manager hat Google in Jetpack eine einheitliche Anlaufstelle geschaffen, die Passkeys, gespeicherte Passwörter und föderierte Identitäten wie „Sign in with Google” unter einem Dach vereint – und gleichzeitig die Grundlage für eine passwortlose Zukunft legt.
Was ist das?
Der Credential Manager ist eine Jetpack-Bibliothek (androidx.credentials), die als Abstraktionsschicht über den verschiedenen Credential-Providern des Systems liegt. Ein Provider kann der eingebaute Android-Passwortmanager, Google Password Manager, ein Drittanbieter wie 1Password oder das FIDO2-Subsystem für Passkeys sein.
Statt mehrere SDKs einzubinden, rufst du eine einzige API auf: CredentialManager.getCredential(…). Das System blendet automatisch alle verfügbaren Optionen ein – priorisiert nach Nutzerpräferenz und Geräteunterstützung. Für den Nutzer erscheint ein einheitlicher Bottom-Sheet-Dialog, der weder deine App-Identität noch die technische Herkunft des Providers preisgibt.
Im Roadmap-Kontext ist der Credential Manager der offizielle Weg, Platform APIs für Authentifizierung zu nutzen (Phase 9). Er löst die ältere SmartLock-for-Passwords-API ab, die seit 2022 als deprecated gilt, und ersetzt auch die direkte FIDO2-Integration, die deutlich mehr Boilerplate erforderte.
Wie funktioniert es?
Der Ablauf besteht aus zwei Richtungen: Anmelden (Get Credential) und Registrieren (Create Credential).
Anmelden
Du erzeugst eine GetCredentialRequest und listest darin alle Credential-Typen auf, die deine App akzeptiert:
val getPasswordOption = GetPasswordOption()
val getPasskeyOption = GetPublicKeyCredentialOption(requestJson = buildFidoAssertionJson())
val request = GetCredentialRequest(
credentialOptions = listOf(getPasskeyOption, getPasswordOption)
)
Anschließend rufst du credentialManager.getCredential(context, request) auf. Das Ergebnis enthält ein Credential-Objekt, das du per when-Ausdruck auswertest:
when (val credential = result.credential) {
is PublicKeyCredential -> verifyPasskeyOnServer(credential.authenticationResponseJson)
is PasswordCredential -> loginWithPassword(credential.id, credential.password)
is CustomCredential -> handleFederated(credential)
}
Registrieren
Bei der Passkey-Registrierung erzeugst du eine CreatePublicKeyCredentialRequest mit einem JSON-String nach FIDO2-Spezifikation und rufst credentialManager.createCredential(context, request) auf. Der Dialog fordert den Nutzer auf, einen Passkey im bevorzugten Provider zu speichern.
Technische Voraussetzungen
- Mindestziel: Die Bibliothek läuft ab API 23 (Android 6.0); Passkeys benötigen Android 9+ mit aktuellen Google Play Services.
- Dependency:
implementation("androidx.credentials:credentials:1.3.0")pluscredentials-play-services-authfür Play-Services-Backends. - Coroutines: Alle API-Aufrufe sind
suspend-Funktionen und gehören in einenviewModelScopeoder ein dediziertesAuthRepository.
In der Praxis
Angenommen, du baust einen Login-Screen mit Jetpack Compose. Der saubere Architekturschnitt lautet: Der CredentialManager-Aufruf wandert in ein AuthRepository, das im ViewModel per Coroutine ausgeführt wird. Die Compose-UI reagiert auf einen UiState – kein direkter API-Aufruf in einem Composable.
class AuthRepository(private val credentialManager: CredentialManager) {
suspend fun signIn(context: Context): SignInResult {
val request = GetCredentialRequest(
listOf(
GetPublicKeyCredentialOption(buildAssertionJson()),
GetPasswordOption()
)
)
return try {
val response = credentialManager.getCredential(context, request)
mapToSignInResult(response.credential)
} catch (e: NoCredentialException) {
SignInResult.NoCredential
} catch (e: GetCredentialCancellationException) {
SignInResult.Cancelled
}
}
}
Typische Stolperfalle: Zu früh aufrufen.
getCredential muss aus einem Context heraus aufgerufen werden, der an ein aktives Activity-Fenster gebunden ist – üblicherweise eine ComponentActivity. Rufst du die Methode beim App-Start auf, bevor der Nutzer eine Aktion ausgeführt hat, erhältst du unter Umständen einen leeren Bottom-Sheet oder eine GetCredentialException. Die Faustregel: Starte den Credential-Abruf immer als Reaktion auf eine explizite Nutzeraktion (Button-Tap), nicht in einem LaunchedEffect beim ersten Composition.
Eine zweite häufige Falle ist eine fehlende oder fehlerhafte Serverkonfiguration für Passkeys. Passkeys erfordern, dass dein Server eine .well-known/assetlinks.json (Digital Asset Links) sowie eine FIDO2-konforme API bereitstellt. Fehlt das, schlägt die Registrierung lautlos fehl oder liefert eine kryptische Fehlermeldung zurück. Prüfe diese Konfiguration frühzeitig, idealerweise mit dem Tool adb shell pm get-app-links.
Fazit
Der Credential Manager ist der zentrale Baustein für sichere und zukunftsfähige Authentifizierung in Android. Er abstrahiert die Komplexität verschiedener Credential-Provider, unterstützt Passkeys als phishing-resistente Alternative zu Passwörtern und lässt sich sauber in eine Jetpack-Compose-Architektur einbetten. Prüfe in deinem nächsten Projekt, ob dein Login-Fluss noch auf SmartLock oder einem eigenen FIDO2-Client basiert – und ersetze ihn durch einen CredentialManager-Aufruf im Repository-Layer. Schreib anschließend einen Instrumentierungstest, der den kompletten Sign-in-Pfad gegen eine Test-Backend-Instanz durchläuft, und beobachte im Logcat, welche Credential-Provider das System aktiviert. Dieses Debugging-Ritual zeigt dir schneller als jede Dokumentation, ob deine Digital-Asset-Links korrekt sind und ob der Passkey-Flow wirklich end-to-end funktioniert.