Nutzer mit Credential Manager anmelden

Credential Manager ist eine Jetpack API, die mehrere Anmeldemethoden wie Nutzername und Passwort, Passkeys und Lösungen für die föderierte Anmeldung (z. B. „Über Google anmelden“) in einer einzigen API unterstützt. Dadurch wird die Integration für Entwickler vereinfacht.

Außerdem vereinfacht der Anmeldedaten-Manager die Anmeldung für Nutzer, da die Anmeldeoberfläche unabhängig von der Authentifizierungsmethode verwendet wird.

Auf dieser Seite werden das Konzept von Passkeys und die Schritte zur Implementierung erläutert. für Authentifizierungslösungen, einschließlich Passkeys, mithilfe der Credential Manager API Auf der separaten FAQ-Seite finden Sie Antworten auf detailliertere, spezifischere Fragen.

Ihr Feedback ist ein wichtiger Bestandteil der Verbesserung der Credential Manager API. Wenn Sie Probleme finden oder Ideen zur Verbesserung der API haben, können Sie sich über den folgenden Link an uns wenden:

Feedback geben

Passkeys

Passkeys sind ein sicherer und einfacherer Ersatz von Passwörtern. Mit Passkeys können sich Nutzer über einen biometrischen Sensor (z. B. Fingerabdruck oder Gesichtserkennung), eine PIN oder ein Muster in Apps und auf Websites anmelden. So können sich Nutzer ganz einfach anmelden, ohne sich Nutzernamen oder Passwörter merken zu müssen.

Passkeys basieren auf WebAuthn (Web Authentication), einem Standard, der gemeinsam von der FIDO Alliance und dem World Wide Web Consortium (W3C) entwickelt wurde. WebAuthn verwendet die Public-Key-Kryptografie, um den Nutzer zu authentifizieren. Die Website oder App, bei der sich der Nutzer anmeldet, kann den öffentlichen Schlüssel sehen und speichern, aber niemals den privaten Schlüssel. Der private Schlüssel wird geheim und sicher aufbewahrt. Da der Schlüssel eindeutig ist und mit der Website oder App verknüpft sind, können Passkeys nicht durch Phishing geschützt werden, was die Sicherheit erhöht.

Mit dem Anmeldedaten-Manager können Nutzer Passkeys erstellen und in Google Passwortmanager.

Eine Anleitung zur Implementierung finden Sie unter Nutzerauthentifizierung mit Passkeys. für die nahtlose Passkey-Authentifizierung.

Voraussetzungen

Führe die Schritte in diesem Abschnitt aus, um den Anmeldedaten-Manager zu verwenden.

Aktuelle Plattformversion verwenden

Der Credential Manager wird ab Android 4.4 (API-Level 19) unterstützt.

Abhängigkeiten zur App hinzufügen

Fügen Sie dem Build-Skript Ihres App-Moduls die folgenden Abhängigkeiten hinzu:

Kotlin

dependencies {
    implementation("androidx.credentials:credentials:1.5.0-alpha05")

    // optional - needed for credentials support from play services, for devices running
    // Android 13 and below.
    implementation("androidx.credentials:credentials-play-services-auth:1.5.0-alpha05")
}

Cool

dependencies {
    implementation "androidx.credentials:credentials:1.5.0-alpha05"

    // optional - needed for credentials support from play services, for devices running
    // Android 13 and below.
    implementation "androidx.credentials:credentials-play-services-auth:1.5.0-alpha05"
}

Klassen in der ProGuard-Datei beibehalten

Fügen Sie der proguard-rules.pro-Datei Ihres Moduls die folgenden Anweisungen hinzu:

-if class androidx.credentials.CredentialManager
-keep class androidx.credentials.playservices.** {
  *;
}

Weitere Informationen zum Verkleinern, Verschleißen und Optimieren Ihrer App

Unterstützung für Digital Asset Links hinzufügen

Wenn du die Passkey-Unterstützung für deine Android-App aktivieren möchtest, verknüpfe deine App mit einem die Ihrer App gehört. Sie können diese Verknüpfung deklarieren, indem Sie die folgenden Schritten:

  1. Erstellen Sie eine Digital Asset Links-JSON-Datei. Wenn Sie beispielsweise angeben möchten, dass die Website https://signin.example.com und eine Android-App mit dem Paketnamen com.example Anmeldedaten gemeinsam nutzen können, erstellen Sie eine Datei namens assetlinks.json mit folgendem Inhalt:

    [
      {
        "relation" : [
          "delegate_permission/common.handle_all_urls",
          "delegate_permission/common.get_login_creds"
        ],
        "target" : {
          "namespace" : "android_app",
          "package_name" : "com.example.android",
          "sha256_cert_fingerprints" : [
            SHA_HEX_VALUE
          ]
        }
      }
    ]
    

    Das Feld relation ist ein Array mit einer oder mehreren Strings, die die deklarierte Beziehung beschreiben. Wenn Sie angeben möchten, dass Apps und Websites Anmeldedaten gemeinsam nutzen, geben Sie die Beziehungen als delegate_permission/handle_all_urls und delegate_permission/common.get_login_creds an.

    Das Feld target ist ein Objekt, das den Inhalt angibt, den die Deklaration enthalten soll gilt. Die folgenden Felder identifizieren eine Website:

    namespace web
    site

    Die URL der Website im Format https://domain[:optional_port]; für Beispiel: https://www.example.com.

    domain muss vollständig qualifiziert sein und optional_port muss weggelassen werden, wenn Port 443 für HTTPS verwendet wird.

    Ein site-Ziel kann nur eine Stammdomain sein: Sie können keine App-Verknüpfung auf ein bestimmtes Unterverzeichnis beschränken. Die URL darf keinen Pfad enthalten, z. B. keinen abschließenden Schrägstrich.

    Subdomains gelten nicht als Übereinstimmung. Wenn Sie also domain als www.example.com angeben, ist die Domain www.counter.example.com nicht mit Ihrer App verknüpft.

    Die folgenden Felder identifizieren eine Android-App:

    namespace android_app
    package_name Der im Manifest der App deklarierte Paketname. Beispiel: com.example.android
    sha256_cert_fingerprints SHA256-Fingerabdrücke der Signaturzertifikat an.
  2. Hosten Sie die Digital Assets Link-JSON-Datei am folgenden Speicherort auf der angemeldete Domain:

    https://domain[:optional_port]/.well-known/assetlinks.json
    

    Wenn Ihre Anmeldedomain beispielsweise signin.example.com ist, hosten Sie die JSON-Datei unter https://signin.example.com/.well-known/assetlinks.json.

    Der MIME-Typ der Digital Asset Link-Datei muss JSON sein. Achten Sie darauf, sendet der Server in der Antwort einen Content-Type: application/json-Header.

  3. Ihr Host muss Google erlauben, Ihre Digital Asset Link-Datei abzurufen. Wenn du eine robots.txt-Datei hast, muss der Googlebot-Agent diese /.well-known/assetlinks.json abrufen. Die meisten Websites dürfen automatischen Agenten, Dateien im Pfad /.well-known/ abzurufen, damit andere Dienste können auf die Metadaten in diesen Dateien zugreifen:

    User-agent: *
    Allow: /.well-known/
    
  4. Fügen Sie der Manifestdatei unter <application> die folgende Zeile hinzu:

    <meta-data android:name="asset_statements" android:resource="@string/asset_statements" />
    
  5. Wenn du die Passwort-Anmeldung über den Anmeldedaten-Manager verwendest, folge diesem Schritt, um die Verknüpfung digitaler Assets im Manifest zu konfigurieren. Dieser Schritt ist nicht erforderlich, wenn Sie nur Passkeys verwenden.

    Deklariere die Verknüpfung in der Android-App. Fügen Sie ein Objekt hinzu, das die assetlinks.json Dateien zum Laden. Du musst allen Apostrophe entkommen und Anführungszeichen, die Sie in der Zeichenfolge verwenden. Beispiel:

    <string name="asset_statements" translatable="false">
    [{
      \"include\": \"https://signin.example.com/.well-known/assetlinks.json\"
    }]
    </string>
    
    > GET /.well-known/assetlinks.json HTTP/1.1
    > User-Agent: curl/7.35.0
    > Host: signin.example.com
    
    < HTTP/1.1 200 OK
    < Content-Type: application/json
    

Anmeldedaten-Manager konfigurieren

Fügen Sie zum Konfigurieren und Initialisieren eines CredentialManager-Objekts eine Logik wie diese hinzu: Folgendes:

Kotlin

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
val credentialManager = CredentialManager.create(context)

Java

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
CredentialManager credentialManager = CredentialManager.create(context)

Anmeldedatenfelder angeben

Unter Android 14 und höher kann das Attribut isCredential verwendet werden, um Anmeldedatenfelder wie Nutzernamen- oder Passwortfelder anzugeben. Dieses Attribut gibt an, dass diese Ansicht ein Anmeldedatenfeld ist, mit dem gearbeitet werden soll Anmeldedaten-Manager und externe Anbieter von Anmeldedaten, während das automatische Ausfüllen unterstützt wird -Dienste bieten bessere Autofill-Vorschläge. Wann die App die Anmeldedaten verwendet Credential Manager-API ist die Ansicht am unteren Rand mit den verfügbaren Anmeldedaten. angezeigt. Das Autofill-Dialogfeld muss nicht mehr für Nutzername oder Passwort. Auch hier ist es nicht notwendig, die Autofill-Funktion Dialogfeld zum Speichern von Passwörtern, da die App die Credential Manager API anfordert um die Anmeldedaten zu speichern.

Wenn Sie das isCredential-Attribut verwenden möchten, fügen Sie es den entsprechenden Datenansichten hinzu:

<TextView
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:isCredential="true"
...
 />

Nutzer anmelden

So rufen Sie alle Passkey- und Passwortoptionen ab, die mit dem Nutzerkonto anmelden, führen Sie diese Schritte aus:

  1. Initialisieren Sie die Optionen für die Passwort- und Passkey-Authentifizierung:

    Kotlin

    // Retrieves the user's saved password for your app from their
    // password provider.
    val getPasswordOption = GetPasswordOption()
    
    // Get passkey from the user's public key credential provider.
    val getPublicKeyCredentialOption = GetPublicKeyCredentialOption(
        requestJson = requestJson
    )

    Java

    // Retrieves the user's saved password for your app from their
    // password provider.
    GetPasswordOption getPasswordOption = new GetPasswordOption();
    
    // Get passkey from the user's public key credential provider.
    GetPublicKeyCredentialOption getPublicKeyCredentialOption =
            new GetPublicKeyCredentialOption(requestJson);
  2. Verwende die im vorherigen Schritt abgerufenen Optionen, um die Anmeldeanfrage zu erstellen.

    Kotlin

    val getCredRequest = GetCredentialRequest(
        listOf(getPasswordOption, getPublicKeyCredentialOption)
    )

    Java

    GetCredentialRequest getCredRequest = new GetCredentialRequest.Builder()
        .addCredentialOption(getPasswordOption)
        .addCredentialOption(getPublicKeyCredentialOption)
        .build();
  3. Starten Sie den Anmeldevorgang:

    Kotlin

    coroutineScope.launch {
        try {
            val result = credentialManager.getCredential(
                // Use an activity-based context to avoid undefined system UI
                // launching behavior.
                context = activityContext,
                request = getCredRequest
            )
            handleSignIn(result)
        } catch (e : GetCredentialException) {
            handleFailure(e)
        }
    }
    
    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")
            }
        }
    }

    Java

    credentialManager.getCredentialAsync(
        // Use activity based context to avoid undefined
        // system UI launching behavior
        activity,
        getCredRequest,
        cancellationSignal,
        <executor>,
        new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
            @Override
            public void onResult(GetCredentialResponse result) {
                handleSignIn(result);
            }
    
            @Override
            public void onError(GetCredentialException e) {
                handleFailure(e);
            }
        }
    );
    
    public void handleSignIn(GetCredentialResponse result) {
        // Handle the successfully returned credential.
        Credential credential = result.getCredential();
        if (credential instanceof PublicKeyCredential) {
            String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson();
            // Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate
        } else if (credential instanceof PasswordCredential) {
            String username = ((PasswordCredential) credential).getId();
            String password = ((PasswordCredential) credential).getPassword();
            // Use id and password to send to your server to validate and authenticate
        } else if (credential instanceof CustomCredential) {
            if (ExampleCustomCredential.TYPE.equals(credential.getType())) {
                try {
                    ExampleCustomCredential customCred = ExampleCustomCredential.createFrom(customCredential.getData());
                    // Extract the required credentials and complete the
                    // authentication as per the federated sign in or any external
                    // sign in library flow
                } catch (ExampleCustomCredential.ExampleCustomCredentialParsingException e) {
                    // 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 folgende Beispiel zeigt, wie die JSON-Anfrage formatiert wird, wenn Sie einen Passkey erhalten:

{
  "challenge": "T1xCsnxM2DNL2KdK5CLa6fMhD7OBqho6syzInk_n-Uo",
  "allowCredentials": [],
  "timeout": 1800000,
  "userVerification": "required",
  "rpId": "credential-manager-app-test.glitch.me"
}

Im folgenden Beispiel wird gezeigt, wie eine JSON-Antwort aussehen könnte, nachdem Sie Anmeldedaten für einen öffentlichen Schlüssel erhalten haben:

{
  "id": "KEDetxZcUfinhVi6Za5nZQ",
  "type": "public-key",
  "rawId": "KEDetxZcUfinhVi6Za5nZQ",
  "response": {
    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiVDF4Q3NueE0yRE5MMktkSzVDTGE2Zk1oRDdPQnFobzZzeXpJbmtfbi1VbyIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
    "authenticatorData": "j5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGQdAAAAAA",
    "signature": "MEUCIQCO1Cm4SA2xiG5FdKDHCJorueiS04wCsqHhiRDbbgITYAIgMKMFirgC2SSFmxrh7z9PzUqr0bK1HZ6Zn8vZVhETnyQ",
    "userHandle": "2HzoHm_hY0CjuEESY9tY6-3SdjmNHOoNqaPDcZGzsr0"
  }
}

Ausnahmen behandeln, wenn keine Anmeldedaten verfügbar sind

Es kann sein, dass der Nutzer keine Anmeldedaten hat, keine Einwilligung zur Verwendung verfügbarer Anmeldedaten erteilen. Wenn getCredential() aufgerufen wird und keine Anmeldedaten gefunden werden, wird NoCredentialException zurückgegeben. In diesem Fall sollte Ihr Code den NoCredentialException Instanzen.

Kotlin

try {
  val credential = credentialManager.getCredential(credentialRequest)
} catch (e: NoCredentialException) {
  Log.e("CredentialManager", "No credential available", e)
}

Java

try {
  Credential credential = credentialManager.getCredential(credentialRequest);
} catch (NoCredentialException e) {
  Log.e("CredentialManager", "No credential available", e);
}

Unter Android 14 oder höher können Sie die Latenz beim Anzeigen des Kontos reduzieren mithilfe der Methode prepareGetCredential() vor dem Aufruf getCredential().

Kotlin

val response = credentialManager.prepareGetCredential(
  GetCredentialRequest(
    listOf(
      <getPublicKeyCredentialOption>,
      <getPasswordOption>
    )
  )
}

Java

GetCredentialResponse response = credentialManager.prepareGetCredential(
  new GetCredentialRequest(
    Arrays.asList(
      new PublicKeyCredentialOption(),
      new PasswordOption()
    )
  )
);

Mit der Methode prepareGetCredential() werden keine UI-Elemente aufgerufen. Sie hilft Ihnen nur bei der Vorbereitung, damit Sie den verbleibenden Vorgang zum Abrufen von Anmeldedaten (mit Benutzeroberflächen) später über die getCredential() API starten können.

Die im Cache gespeicherten Daten werden in einem PrepareGetCredentialResponse-Objekt zurückgegeben. Wenn Wenn Anmeldedaten vorhanden sind, werden die Ergebnisse im Cache gespeichert. die verbleibende getCredential() API später starten, um das Konto aufzurufen mit den im Cache gespeicherten Daten.

Registrierungsablauf

Sie können einen Nutzer entweder mit einem Passkey oder einem Passwort für die Authentifizierung registrieren.

Passkey erstellen

Wenn Sie Nutzern die Möglichkeit geben möchten, einen Passkey zu registrieren und zur erneuten Authentifizierung zu verwenden, Die Anmeldedaten eines Nutzers werden mit einem CreatePublicKeyCredentialRequest-Objekt registriert.

Kotlin

fun createPasskey(requestJson: String, preferImmediatelyAvailableCredentials: Boolean) {
    val createPublicKeyCredentialRequest = CreatePublicKeyCredentialRequest(
        // Contains the request in JSON format. Uses the standard WebAuthn
        // web JSON spec.
        requestJson = requestJson,
        // Defines whether you prefer to use only immediately available
        // credentials, not hybrid credentials, to fulfill this request.
        // This value is false by default.
        preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials,
    )

    // Execute CreateCredentialRequest asynchronously to register credentials
    // for a user account. Handle success and failure cases with the result and
    // exceptions, respectively.
    coroutineScope.launch {
        try {
            val result = credentialManager.createCredential(
                // Use an activity-based context to avoid undefined system
                // UI launching behavior
                context = activityContext,
                request = createPublicKeyCredentialRequest,
            )
            handlePasskeyRegistrationResult(result)
        } catch (e : CreateCredentialException){
            handleFailure(e)
        }
    }
}

fun handleFailure(e: CreateCredentialException) {
    when (e) {
        is CreatePublicKeyCredentialDomException -> {
            // Handle the passkey DOM errors thrown according to the
            // WebAuthn spec.
            handlePasskeyError(e.domError)
        }
        is CreateCredentialCancellationException -> {
            // The user intentionally canceled the operation and chose not
            // to register the credential.
        }
        is CreateCredentialInterruptedException -> {
            // Retry-able error. Consider retrying the call.
        }
        is CreateCredentialProviderConfigurationException -> {
            // Your app is missing the provider configuration dependency.
            // Most likely, you're missing the
            // "credentials-play-services-auth" module.
        }
        is CreateCredentialUnknownException -> ...
        is CreateCredentialCustomException -> {
            // You have encountered an error from a 3rd-party SDK. If you
            // make the API call with a request object that's a subclass of
            // CreateCustomCredentialRequest using a 3rd-party SDK, then you
            // should check for any custom exception type constants within
            // that SDK to match with e.type. Otherwise, drop or log the
            // exception.
        }
        else -> Log.w(TAG, "Unexpected exception type ${e::class.java.name}")
    }
}

Java

public void createPasskey(String requestJson, boolean preferImmediatelyAvailableCredentials) {
    CreatePublicKeyCredentialRequest createPublicKeyCredentialRequest =
            // `requestJson` contains the request in JSON format. Uses the standard
            // WebAuthn web JSON spec.
            // `preferImmediatelyAvailableCredentials` defines whether you prefer
            // to only use immediately available credentials, not  hybrid credentials,
            // to fulfill this request. This value is false by default.
            new CreatePublicKeyCredentialRequest(
                requestJson, preferImmediatelyAvailableCredentials);

    // Execute CreateCredentialRequest asynchronously to register credentials
    // for a user account. Handle success and failure cases with the result and
    // exceptions, respectively.
    credentialManager.createCredentialAsync(
        // Use an activity-based context to avoid undefined system
        // UI launching behavior
        requireActivity(),
        createPublicKeyCredentialRequest,
        cancellationSignal,
        executor,
        new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() {
            @Override
            public void onResult(CreateCredentialResponse result) {
                handleSuccessfulCreatePasskeyResult(result);
            }

            @Override
            public void onError(CreateCredentialException e) {
                if (e instanceof CreatePublicKeyCredentialDomException) {
                    // Handle the passkey DOM errors thrown according to the
                    // WebAuthn spec.
                    handlePasskeyError(((CreatePublicKeyCredentialDomException)e).getDomError());
                } else if (e instanceof CreateCredentialCancellationException) {
                    // The user intentionally canceled the operation and chose not
                    // to register the credential.
                } else if (e instanceof CreateCredentialInterruptedException) {
                    // Retry-able error. Consider retrying the call.
                } else if (e instanceof CreateCredentialProviderConfigurationException) {
                    // Your app is missing the provider configuration dependency.
                    // Most likely, you're missing the
                    // "credentials-play-services-auth" module.
                } else if (e instanceof CreateCredentialUnknownException) {
                } else if (e instanceof CreateCredentialCustomException) {
                    // You have encountered an error from a 3rd-party SDK. If
                    // you make the API call with a request object that's a
                    // subclass of
                    // CreateCustomCredentialRequest using a 3rd-party SDK,
                    // then you should check for any custom exception type
                    // constants within that SDK to match with e.type.
                    // Otherwise, drop or log the exception.
                } else {
                  Log.w(TAG, "Unexpected exception type "
                          + e.getClass().getName());
                }
            }
        }
    );
}

JSON-Anfrage formatieren

Nachdem Sie einen Passkey erstellt haben, müssen Sie ihn mit dem Konto eines Nutzers verknüpfen und den öffentlichen Schlüssel des Passkeys auf Ihrem Server speichern. Das folgende Codebeispiel zeigt, wie die JSON-Anfrage beim Erstellen eines Passkeys formatiert wird.

In diesem Blogpost zur nahtlosen Authentifizierung für Apps geht es um folgende Themen: wie Sie Ihre JSON-Anfrage formatieren, wenn Sie Passkeys erstellen mit Passkeys authentifizieren. Außerdem wird erklärt, warum Passwörter nicht effektiv sind. Authentifizierungslösung, vorhandene biometrische Anmeldedaten nutzen, Verknüpfen Ihrer App mit einer Website, die Ihnen gehört, wie Sie Passkeys erstellen zur Authentifizierung mit Passkeys.

{
  "challenge": "abc123",
  "rp": {
    "name": "Credential Manager example",
    "id": "credential-manager-test.example.com"
  },
  "user": {
    "id": "def456",
    "name": "helloandroid@gmail.com",
    "displayName": "helloandroid@gmail.com"
  },
  "pubKeyCredParams": [
    {
      "type": "public-key",
      "alg": -7
    },
    {
      "type": "public-key",
      "alg": -257
    }
  ],
  "timeout": 1800000,
  "attestation": "none",
  "excludeCredentials": [
    {"id": "ghi789", "type": "public-key"},
    {"id": "jkl012", "type": "public-key"}
  ],
  "authenticatorSelection": {
    "authenticatorAttachment": "platform",
    "requireResidentKey": true,
    "residentKey": "required",
    "userVerification": "required"
  }
}

Werte für Authentifizierungs-Anhang festlegen

Der Parameter authenticatorAttachment kann nur beim Erstellen der Anmeldedaten festgelegt werden . Sie können platform, cross-platform oder keinen Wert angeben. In den meisten Fällen wird kein Wert empfohlen.

  • platform: Registrieren des aktuellen Geräts des Nutzers oder Aufforderung zur Eingabe eines Passworts Nutzer muss nach der Anmeldung ein Upgrade auf Passkeys verwenden, festgelegt authenticatorAttachment bis platform.
  • cross-platform: Dieser Wert wird häufig bei der Registrierung von mehrstufigen Anmeldedaten verwendet und nicht im Kontext eines Passkeys.
  • Kein Wert: Damit Nutzer Passkeys auf ihren bevorzugten Geräten erstellen können (z. B. in den Kontoeinstellungen), sollte der Parameter authenticatorAttachment nicht angegeben werden, wenn ein Nutzer einen Passkey hinzufügen möchte. In den meisten Fällen ist es am besten, den Parameter nicht Option.

Erstellen von Passkeys duplizieren verhindern

Listen Sie die Anmeldedaten-IDs im optionalen Array excludeCredentials auf, um zu verhindern, Einen neuen Passkey erstellen, wenn bereits ein Passkey mit demselben Passkey vorhanden ist Dienstanbieter.

JSON-Antwort verarbeiten

Das folgende Code-Snippet zeigt eine Beispiel-JSON-Antwort zum Erstellen von Anmeldedaten für öffentliche Schlüssel. Weitere Informationen zum Umgang mit den zurückgegebenen Public-Key-Anmeldedaten

{
  "id": "KEDetxZcUfinhVi6Za5nZQ",
  "type": "public-key",
  "rawId": "KEDetxZcUfinhVi6Za5nZQ",
  "response": {
    "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoibmhrUVhmRTU5SmI5N1Z5eU5Ka3ZEaVh1Y01Fdmx0ZHV2Y3JEbUdyT0RIWSIsIm9yaWdpbiI6ImFuZHJvaWQ6YXBrLWtleS1oYXNoOk1MTHpEdll4UTRFS1R3QzZVNlpWVnJGUXRIOEdjVi0xZDQ0NEZLOUh2YUkiLCJhbmRyb2lkUGFja2FnZU5hbWUiOiJjb20uZ29vZ2xlLmNyZWRlbnRpYWxtYW5hZ2VyLnNhbXBsZSJ9",
    "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViUj5r_fLFhV-qdmGEwiukwD5E_5ama9g0hzXgN8thcFGRdAAAAAAAAAAAAAAAAAAAAAAAAAAAAEChA3rcWXFH4p4VYumWuZ2WlAQIDJiABIVgg4RqZaJyaC24Pf4tT-8ONIZ5_Elddf3dNotGOx81jj3siWCAWXS6Lz70hvC2g8hwoLllOwlsbYatNkO2uYFO-eJID6A"
  }
}

Ursprung aus Clientdaten-JSON prüfen

Das origin steht für die Anwendung oder Website, von der eine Anfrage stammt, und wird von Passkeys zum Schutz vor Phishing-Angriffen verwendet. Der Server der Anwendung ist erforderlich, um den Client zu prüfen mit einer Zulassungsliste genehmigter Apps und Websites vergleichen. Wenn der Server eine Anfrage von einer App oder Website von einer unbekannten Quelle erhält, sollte abgelehnt werden.

Im Fall „Web“ steht origin für den Ursprung derselben Website, wobei Sie haben sich mit den Anmeldedaten angemeldet. Bei der URL https://www.example.com:8443/store?category=shoes#athletic ist origin beispielsweise https://www.example.com:8443.

Bei Android-Apps legt der User-Agent origin automatisch auf die Signatur von über die Anruf-App. Diese Signatur sollte auf Ihrem Server als Übereinstimmung mit den Aufrufer der Passkey API validieren. Die Android-origin ist eine URI, die aus dem SHA-256-Hash des APK-Signaturzertifikats abgeleitet wird, z. B.:

android:apk-key-hash:<sha256_hash-of-apk-signing-cert>

Die SHA-256-Hashes der Signaturzertifikate aus einem Schlüsselspeicher können mit dem folgenden Terminalbefehl ermittelt werden:

keytool -list -keystore <path-to-apk-signing-keystore>

Die SHA-256-Hashes haben ein Hexadezimalformat, das durch Doppelpunkte getrennt ist (91:F7:CB:F9:D6:81…) und die Android-Werte origin sind base64url-codiert. Dieses Python-Beispiel zeigt, wie Sie das Hash-Format in ein kompatibles, Durch Doppelpunkt getrenntes Hexadezimalformat:

import binascii
import base64
fingerprint = '91:F7:CB:F9:D6:81:53:1B:C7:A5:8F:B8:33:CC:A1:4D:AB:ED:E5:09:C5'
print("android:apk-key-hash:" + base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))

Ersetzen Sie den Wert für fingerprint durch Ihren eigenen Wert. Hier ist ein Beispiel result:

android:apk-key-hash:kffL-daBUxvHpY-4M8yhTavt5QnFEI2LsexohxrGPYU

Sie können diesen String dann als zulässigen Ursprung auf Ihrem Server abgleichen. Wenn Sie mehrere Signaturzertifikate haben, z. B. Zertifikate für die Fehlerbehebung und Veröffentlichung oder mehrere Apps, wiederholen Sie den Vorgang und akzeptieren Sie alle diese Ursprünge auf dem Server als gültig.

Nutzerpasswort speichern

Wenn der Nutzer einen Nutzernamen und ein Passwort für einen Authentifizierungsvorgang in Ihrem App können Sie Anmeldedaten eines Nutzers registrieren, die zur Authentifizierung des Nutzer. Erstellen Sie dazu ein CreatePasswordRequest-Objekt:

Kotlin

fun registerPassword(username: String, password: String) {
    // Initialize a CreatePasswordRequest object.
    val createPasswordRequest =
            CreatePasswordRequest(id = username, password = password)

    // Create credential and handle result.
    coroutineScope.launch {
        try {
            val result =
                credentialManager.createCredential(
                    // Use an activity based context to avoid undefined
                    // system UI launching behavior.
                    activityContext,
                    createPasswordRequest
                  )
            handleRegisterPasswordResult(result)
        } catch (e: CreateCredentialException) {
            handleFailure(e)
        }
    }
}

Java

void registerPassword(String username, String password) {
    // Initialize a CreatePasswordRequest object.
    CreatePasswordRequest createPasswordRequest =
        new CreatePasswordRequest(username, password);

    // Register the username and password.
    credentialManager.createCredentialAsync(
        // Use an activity-based context to avoid undefined
        // system UI launching behavior
        requireActivity(),
        createPasswordRequest,
        cancellationSignal,
        executor,
        new CredentialManagerCallback<CreateCredentialResponse, CreateCredentialException>() {
            @Override
            public void onResult(CreateCredentialResponse result) {
                handleResult(result);
            }

            @Override
            public void onError(CreateCredentialException e) {
                handleFailure(e);
            }
        }
    );
}

Unterstützung bei der Wiederherstellung von Anmeldedaten

Wenn ein Nutzer keinen Zugriff mehr auf ein Gerät hat, auf dem er seine Anmeldedaten müssen sie möglicherweise aus einem sicheren Online-Back-up wiederherstellen. Weitere Informationen zur Unterstützung dieses Prozesses zur Wiederherstellung von Anmeldedaten finden Sie im Blogpost Sicherheit von Passkeys im Google Passwortmanager im Abschnitt „Zugriff wiederherstellen oder neue Geräte hinzufügen“.

Passwortverwaltungstools mit bekannten URLs von Passkey-Endpunkten unterstützen

Für nahtlose Integration und zukünftige Kompatibilität mit Passwort und Anmeldedaten Managementtools verwenden, empfehlen wir, Unterstützung für bekannte Passkey-Endpunkte hinzuzufügen, URLs. Dies ist ein offenes Protokoll für gemeinsame Parteien zur formalen Bewerbung ihrer Unterstützung für Passkeys und direkte Links für die Passkey-Registrierung und zu verstehen.

  1. Für eine vertrauende Partei bei https://example.com, das über eine Website und Android- und iOS-Apps wäre die bekannte URL https://example.com/.well-known/passkey-endpoints.
  2. Bei der Abfrage der URL sollte die Antwort das folgende Schema verwenden:

    {
      "enroll": "https://example.com/account/manage/passkeys/create"
      "manage": "https://example.com/account/manage/passkeys"
    }
    
  3. Wenn dieser Link direkt in Ihrer App und nicht im Web geöffnet werden soll, verwenden Sie Android-App-Links.

  4. Weitere Informationen finden Sie in der Erklärung zur bekannten URL für Passkey-Endpunkte auf GitHub.

Sie können Nutzern beim Verwalten ihrer Passkeys helfen, indem Sie sehen, welcher Anbieter sie erstellt hat

Eine Herausforderung für Nutzer beim Verwalten mehrerer Passkeys, die mit einer bestimmten App verknüpft sind, besteht darin, den richtigen Passkey zum Bearbeiten oder Löschen zu identifizieren. Zur Unterstützung bei App und Websites zusätzliche Informationen enthalten, Informationen wie den Anbieter, der den Berechtigungsnachweis erstellt hat, das Erstellungsdatum und das Datum der letzten Verwendung in einer Liste der Passkeys auf dem Einstellungsbildschirm der App.Der Anbieter erhalten Sie, indem Sie die zugehörige AAGUID untersuchen. mit dem entsprechenden Passkey. Die AAGUID ist Teil der Authenticator-Daten eines Passkeys.

Wenn ein Nutzer beispielsweise mit dem Google Passwortmanager auf einem Android-Gerät einen Passkey erstellt, erhält der RP eine AAGUID, die in etwa so aussieht: „ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4“. Die vertrauende Partei kann den Passkey in der Passkey-Liste mit einem Vermerk versehen, dass er mit Google Passwortmanager.

Um eine AAGUID einem Passkey-Anbieter zuzuordnen, können RPs eine aus der Community Repository von AAGUIDs. Suchen Sie in dieser Liste nach der AAGUID, um den Namen und das Symbol des Passkey-Anbieters zu finden.

Weitere Informationen zur AAGUID-Integration

Häufige Fehler beheben

Die folgende Tabelle enthält einige häufige Fehlercodes und -beschreibungen sowie einige Informationen zu ihren Ursachen:

Fehlercode und -beschreibung Ursache
Fehler beim Starten der Anmeldung: 16: Der Anrufer wurde aus folgendem Grund vorübergehend blockiert: zu viele abgebrochene Aufforderungen zur Anmeldung angezeigt.

Wenn während der Entwicklung eine Wartezeit von 24 Stunden eintritt, können Sie es zurücksetzen, indem Sie App-Speicher.

Wenn Sie die Wartezeit auf einem Testgerät oder Emulator aktivieren oder deaktivieren möchten, gehen Sie zu in die Telefon App und geben Sie den folgenden Code ein: *#*#66382723#*#* Die Telefon App löscht sämtliche Eingaben und kann aber es wird keine Bestätigungsmeldung angezeigt.

Fehler beim Starten der Anmeldung: 8: Unbekannter interner Fehler.
  1. Das Gerät ist nicht richtig mit dem Google-Konto eingerichtet.
  2. Die Passkey-JSON wird nicht korrekt erstellt.
CreatePublicKeyCredentialDomException: Die eingehende Anfrage kann nicht validiert werden Die Paket-ID der App ist nicht auf Ihrem Server registriert. Prüfen Sie dies in Ihrer serverseitigen Integration.
CreateCredentialUnknownException: Beim Speichern des Passworts wurde das Passwort gefunden Fehlerantwort von One Tap 16: Speichern des Passworts wird übersprungen, da der Nutzer wird wahrscheinlich mit der Android-Funktion „Autofill“ angezeigt, Dieser Fehler tritt nur unter Android 13 und niedriger auf und nur, wenn Google der Autofill-Anbieter ist. In diesem Fall sehen Nutzer Aufforderung von Autofill und das Passwort wird im Google-Passwort gespeichert Administrator. Die mit Autofill mit Google gespeicherten Anmeldedaten werden bidirektional mit der Credential Manager API geteilt. Daher wird dieser Fehler ignoriert werden kann.

Weitere Informationen

Weitere Informationen zur Credential Manager API und zu Passkeys finden Sie in den folgenden Ressourcen: