[Credential Manager](https://developer.android.com/jetpack/androidx/releases/credentials) is a Jetpack API that supports multiple sign-in methods,
such as username and password, passkeys, and federated sign-in solutions (such
as Sign-in with Google) in a single API, thus simplifying the integration for
developers.

Furthermore, for users, Credential Manager unifies the sign-in interface across
authentication methods, making it clearer and easier for users to sign into
apps, regardless of the method they choose.
| **Note:** Passkeys are supported only on devices that run Android 9 (API level 28) or higher. On devices that run a version between Android 4.4 (API level 19) and Android 8.1 (API level 27), inclusive, only passwords and Sign in with Google are supported.

This page explains the concept of passkeys and the steps to implementing
client-side support for authentication solutions, including passkeys, using the
Credential Manager API. There is also a separate [FAQ page](https://developer.android.com/identity/sign-in/credential-manager-faq) that provides
answers to more detailed, specific questions.

## About passkeys

[Passkeys](https://developers.google.com/identity/passkeys) are a safer and easier replacement for passwords. With passkeys,
users can sign in to apps and websites using a biometric sensor (such as a
fingerprint or facial recognition), PIN, or pattern. This provides a seamless
sign-in experience, freeing your users from having to remember usernames or
passwords.

Passkeys rely on WebAuthn (Web Authentication), a standard jointly developed by
the FIDO Alliance and the World Wide Web Consortium (W3C). WebAuthn uses
public-key cryptography to authenticate the user. The website or app that the
user is signing into can see and store the public key, but never the private
key. The private key is kept secret and safe. And because the key is unique and
tied to the website or app, passkeys are un-phishable, adding further security.

Credential Manager allows users to create passkeys and store them in [Google
Password Manager](https://support.google.com/accounts/answer/6208650).

Read [User authentication with passkeys](https://developer.android.com/design/ui/mobile/guides/patterns/passkeys) for guidance on how to implement
seamless passkey authentication flows with Credential Manager.

## Prerequisites

| **Note:** If your app requires non-discoverable [FIDO credentials](https://developers.google.com/identity/fido/android/native-apps) or uses physical security keys, you should continue to use FIDO at this time.

To use Credential Manager, complete the steps in this section.

### Use a recent platform version

Credential Manager is supported on Android 4.4 (API level 19) and higher.

### Add dependencies to your app

Add the following dependencies to your app module's build script, to use the
latest version of the [Credential Manager library](https://developer.android.com/jetpack/androidx/releases/credentials):  

### Kotlin

```kotlin
dependencies {
    implementation("androidx.credentials:credentials:1.6.0-beta01")
    implementation("androidx.credentials:credentials-play-services-auth:1.6.0-beta01")
}
```

### Groovy

```groovy
dependencies {
    implementation "androidx.credentials:credentials:1.6.0-beta01"
    implementation "androidx.credentials:credentials-play-services-auth:1.6.0-beta01"
}
```
| **Note:** All projects should use the [latest available version of
| androidx.credentials](https://developer.android.com/jetpack/androidx/releases/credentials). Versions of androidx.credentials earlier than v1.2 throw an `UnsupportedOperationException("Post-U not supported yet")` exception when run on Android 14.

Learn more about how to [shrink, obfuscate, and optimize your app](https://developer.android.com/build/shrink-code).

### Add support for Digital Asset Links

To enable passkey support for your Android app, associate your app with a
website that your app owns. You can declare this association by completing the
following steps:

1. Create a Digital Asset Links JSON file. For example, to declare that the
   website `https://signin.example.com` and an Android app with the package
   name `com.example` can share sign-in credentials, create a file named
   `assetlinks.json` with the following content:

       [
         {
           "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
             ]
           }
         }
       ]

   The `relation` field is an array of one or more strings that describe the
   relationship being declared. To declare that apps and sites share sign-in
   credentials, specify the relationships as
   `delegate_permission/handle_all_urls` and
   `delegate_permission/common.get_login_creds`.

   The `target` field is an object that specifies the asset the declaration
   applies to. The following fields identify a website:

   |-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
   | `namespace` | `web`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
   | `site`      | The website's URL, in the format `https://`<var translate="no">domain</var>`[:`<var translate="no">optional_port</var>`]`; for example, `https://www.example.com`. The <var translate="no">domain</var> must be fully-qualified., and <var translate="no">optional_port</var> must be omitted when using port 443 for HTTPS. A `site` target can only be a root domain: you cannot limit an app association to a specific subdirectory. Don't include a path in the URL, such as a trailing slash. Subdomains are not considered to match: that is, if you specify the <var translate="no">domain</var> as `www.example.com`, the domain `www.counter.example.com` is not associated with your app. |

   The following fields identify an Android app:

   |----------------------------|---------------------------------------------------------------------------------------------------------------------------------|
   | `namespace`                | `android_app`                                                                                                                   |
   | `package_name`             | The package name declared in the app's manifest. For example, `com.example.android`                                             |
   | `sha256_cert_fingerprints` | The SHA256 fingerprints of your app's [signing certificate](https://developer.android.com/studio/publish/app-signing#sign-apk). |

2. Host the Digital Assets Link JSON file at the following location on the
   sign-in domain:

       https://<var translate="no">domain</var>[:<var translate="no">optional_port</var>]/.well-known/assetlinks.json

   For example, if your sign-in domain is `signin.example.com`, host the JSON
   file at `https://signin.example.com/.well-known/assetlinks.json`.

   The MIME type for the Digital Assets Link file must be JSON. Verify that the
   server sends a `Content-Type: application/json` header in the response.
3. Verify that your host permits Google to retrieve your Digital Asset Link
   file. If you have a `robots.txt` file, it must allow the Googlebot agent to
   retrieve `/.well-known/assetlinks.json`. Most sites can allow any automated
   agent to retrieve files in the `/.well-known/` path so that other services
   can access the metadata in those files:

       User-agent: *
       Allow: /.well-known/

4. Add the following line to the manifest file under `<application>`:

       <meta-data android:name="asset_statements" android:resource="@string/asset_statements" />

5. If you are using password sign-in through Credential Manager, follow this
   step to configure digital asset linking in manifest. *This step is not
   required if you are only using passkeys.*

   Declare the association in the Android app. Add an object that specifies the
   `assetlinks.json` files to load. You must escape any apostrophes and
   quotation marks you use in the string. For example:  

       <string name="asset_statements" translatable="false">
       [{
         \"include\": \"https://signin.example.com/.well-known/assetlinks.json\"
       }]
       </string>

   **Note:** the `https://signin.example.com/.well-known/assetlinks.json` link must return a 200 HTTP response with a JSON MIME Content-Type header. Returning a 301 or 302 HTTP redirect or a non-JSON Content-Type causes verification to fail. The following is an example showing a request and the related response headers.  

       > 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

## Configure the Credential Manager

To configure and initialize a `CredentialManager` object, add logic similar to
the following:  

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

## Indicate credential fields

On Android 14 and higher, the [`isCredential`](https://developer.android.com/reference/android/view/View#attr_android:isCredential) attribute can be used to
indicate credential fields, such as username or password fields. This attribute
indicates that this view is a credential field that is intended to work with
Credential Manager and third party credential providers, while helping autofill
services provide better autofill suggestions. When the app uses the Credential
Manager API, the Credential Manager bottom sheet with available credentials is
displayed and there's no further need to show autofill's fill dialog for
username or password. In a similar way, there's no need to show autofill's save
dialog for passwords, as the app will request Credential Manager API to save the
credentials.

To use the `isCredential` attribute, add it to the relevant Views:  

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

## Sign in your user

To retrieve all the passkey and password options that are associated with the
user's account, complete these steps:

1. Initialize the password and passkey authentication options:

   ```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
   )
         
   ```
2. Use the options retrieved from the previous step to build the
   sign-in request.

   **Note:** Apps shouldn't set the [`origin`](https://developer.android.com/reference/kotlin/androidx/credentials/GetCredentialRequest#origin()) field, with the exception of browsers and similarly privileged apps. [Learn more](https://developer.android.com/training/sign-in/privileged-apps).  

   ```kotlin
   val credentialRequest = GetCredentialRequest(
       listOf(getPasswordOption, getPublicKeyCredentialOption),
   )
         
   ```
3. Launch the sign-in flow:

   ```kotlin
   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
       }
   }
       
   ```  

   ```kotlin
   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")
           }
       }
   }
       
   ```

| **Note:** If the call to Credential Manager was triggered by an explicit
| user action, set `preferImmediatelyAvailableCredentials` to
| `false`. If Credential Manager was opportunistically called, set
| `preferImmediatelyAvailableCredentials` to `true`.
|
| The `preferImmediatelyAvailableCredentials` option defines
| whether you prefer to only use locally-available credentials to fulfill the
| request, instead of credentials from security keys or [hybrid](https://w3c.github.io/webauthn/#dom-authenticatortransport-hybrid)
| key flows. This value is `false` by default.
|
| If you set `preferImmediatelyAvailableCredentials` to
| `true` and there are no immediately available credentials,
| Credential Manager won't show any UI and the request will fail immediately,
| returning [`NoCredentialException`](https://developer.android.com/identity/sign-in/credential-manager#handle-exceptions)
| for get requests and `CreateCredentialNoCreateOptionException` for
| create requests. This is recommended when calling the Credential Manager API
| opportunistically, such as when first opening the app.

The following example shows how to format the JSON request when you get a
passkey:  

    {
      "challenge": "T1xCsnxM2DNL2KdK5CLa6fMhD7OBqho6syzInk_n-Uo",
      "allowCredentials": [],
      "timeout": 1800000,
      "userVerification": "required",
      "rpId": "https://passkeys-codelab.glitch.me/"
    }

The following example shows how a JSON response might look after you get a
public key credential:  

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

### Handle exceptions when no credentials are available

In some cases, the user may not have any credentials available, or the user may
not grant consent to using an available credential. If [`getCredential()`](https://developer.android.com/reference/androidx/credentials/CredentialManager#getCredential(android.content.Context,androidx.credentials.GetCredentialRequest)) is
invoked and no credentials are not found, a [`NoCredentialException`](https://developer.android.com/reference/kotlin/androidx/credentials/exceptions/NoCredentialException) is
returned. If this happens, your code should handle the `NoCredentialException`
instances.  

    coroutineScope {
        try {
            result = credentialManager.getCredential(
                context = activityContext,
                request = credentialRequest
            )
        } catch (e: GetCredentialException) {
            Log.e("CredentialManager", "No credential available", e)
        }
    }

On Android 14 or higher, you can reduce latency when showing the account
selector by using the [`prepareGetCredential()`](https://developer.android.com/reference/androidx/credentials/CredentialManager#prepareGetCredential(androidx.credentials.GetCredentialRequest)) method before calling
`getCredential()`.  

    coroutineScope {
        val response = credentialManager.prepareGetCredential(
            GetCredentialRequest(
                listOf(
                    getPublicKeyCredentialOption,
                    getPasswordOption
                )
            )
        )
    }

The `prepareGetCredential()` method doesn't invoke UI elements. It only helps
you perform the preparation work so that you can later launch the remaining
get-credential operation (which involves UIs) through the `getCredential()` API.

The cached data is returned in a [`PrepareGetCredentialResponse`](https://developer.android.com/reference/androidx/credentials/PrepareGetCredentialResponse) object. If
there are existing credentials, the results will be cached and you can then
later launch the remaining [`getCredential()`](https://developer.android.com/reference/androidx/credentials/CredentialManager#getCredential(android.content.Context,androidx.credentials.PrepareGetCredentialResponse.PendingGetCredentialHandle)) API to bring up the account
selector with the cached data.
| **Note:** Since the bottom sheet is launched automatically, don't introduce unexpected wait times in the UI such as network calls. Always fetch one-time challenges and other passkey configurations (such as a relying party IDs) at the beginning of any app session.

## Registration flows

You can register a user for authentication using either a [passkey](https://developer.android.com/identity/sign-in/credential-manager#create-passkey) or a
[password](https://developer.android.com/identity/sign-in/credential-manager#save-password).
| **Note:** When there is not passkey associated with a registered account, consider [catching an instance of `NoCredentialException`](https://developer.android.com/identity/sign-in/credential-manager#handle-exceptions) to let the user know that they need to create a passkey to support passkey authentication.

### Create a passkey

To give users the choice to enroll a passkey and use it for reauthentication,
register a user credential using a `CreatePublicKeyCredentialRequest` object.  

    suspend 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 {
            try {
                val result = credentialManager.createCredential(
                    // Use an activity-based context to avoid undefined system
                    // UI launching behavior
                    context = activityContext,
                    request = createPublicKeyCredentialRequest,
                )
                //  Handle passkey creation 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.
            }
            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 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}")
        }
    }

| **Note:** Apps shouldn't set the [`origin`](https://developer.android.com/reference/kotlin/androidx/credentials/CreateCredentialRequest#origin()) field, with the exception of browsers and similarly privileged apps. [Learn more](https://developer.android.com/training/sign-in/privileged-apps).

### Format the JSON request

After you create a passkey, you must associate it with a user's account, and
store the passkey's public key on your server. The following code example shows
an how to format the JSON request when you create a passkey.

This [blog post about bringing seamless authentication to your apps](https://medium.com/androiddevelopers/bringing-seamless-authentication-to-your-apps-using-credential-manager-api-b3f0d09e0093#172a) shows
you how to format your JSON request when you create passkeys and when you
authenticate using passkeys. It also explains why passwords aren't an effective
authentication solution, how to leverage existing biometric credentials, how to
associate your app with a website that you own, how to create passkeys, and how
to authenticate using 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"
      }
    }

### Set values for authenticatorAttachment

The `authenticatorAttachment` parameter can only be set at credential creation
time. You can specify `platform`, `cross-platform`, or no value. In most cases,
no value is recommended.

- **`platform`** : To register the user's current device or prompt a password user to upgrade to passkeys after a sign-in, set `authenticatorAttachment` to `platform`.
- **`cross-platform`**: This value is commonly used when enrolling multi-factor credentials and is not used in a passkey context.
- **No value** : To provide users with the flexibility to create passkeys on their preferred devices (such as in account settings), the `authenticatorAttachment` parameter shouldn't be specified when a user chooses to add a passkey. In most cases, leaving the parameter unspecified is the best option.

### Prevent the creation of duplicate passkeys

List credential IDs in the optional [`excludeCredentials`](https://web.dev/articles/webauthn-exclude-credentials) array to prevent
the creation of a new passkey if one already exists with the same passkey
provider.

### Handle the JSON response

The following code snippet shows an example JSON response for creating a public
key credential. Learn more about how to handle the [returned public key
credential](https://web.dev/passkey-registration/#send-the-returned-public-key-credential-to-the-backend).  

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

### Verify origin from client data JSON

The [`origin`](https://www.w3.org/TR/webauthn-2/#dom-collectedclientdata-origin) represents the application or website that a
request comes from, and is used by passkeys to protect against phishing attacks.
Your app's server is required to check the client data origin against an
allowlist of approved apps and websites. If the server receives a request from
an app or website from an unrecognized origin, the request should be rejected.

In the Web case, `origin` reflects [the same-site origin](https://web.dev/same-site-same-origin/#origin) where
the credential was signed in. For example, given a URL of
`https://www.example.com:8443/store?category=shoes#athletic` , the `origin` is
`https://www.example.com:8443`.

For Android apps, the user agent automatically sets `origin` to the signature of
the calling app. This signature should be verified as a match on your server to
validate the caller of the passkey API. The Android `origin` is a URI derived
from the SHA-256 hash of the APK signing certificate, such as:  

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

The SHA-256 hashes of the signing certificates from a keystore can be found by
running the following terminal command:  

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

The SHA-256 hashes are in a colon-delimited hexadecimal format
(`91:F7:CB:F9:D6:81...`), and the Android `origin` values are base64url-encoded.
This Python example demonstrates how to convert the hash format to a compatible,
colon-separated hexadecimal format:  

    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('=', ''))

Replace the value of `fingerprint` with your own value. Here is an example
result:  

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

You can then match that string as an allowed origin on your server. If you have
multiple signing certificates, such as certificates for debugging and release,
or multiple apps, then repeat the process and accept all those origins as valid
on the server.

### Save a user's password

If the user provides a username and password for an authentication flow in your
app, you can register a user credential that can be used to authenticate the
user. To do so, create a `CreatePasswordRequest` object:  

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

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

### Support credential recovery

If a user no longer has access to a device where they had stored their
credentials, they might need to recover from a secure online backup. To learn
more about how to support this credential recovery process, read the section
titled "Recovering access or adding new devices" in this blog post: [Security of
Passkeys in the Google Password Manager](https://security.googleblog.com/2022/10/SecurityofPasskeysintheGooglePasswordManager.html).

## Automatically create passkeys for users

If a user doesn't have a passkey, you can automatically create one on their
behalf the next time they sign in using a password saved on their password
manager. Do so by setting the `isConditionalCreateRequest` field when requesting
public credentials:  

    CreatePublicKeyCredentialRequest(
        // other parameters
        isConditionalCreateRequest: Boolean = true
    )

When the user signs in, a passkey is automatically created and stored in the
user's selected password manager. If using Google Password Manager, the user
must have used (either using Credential Manager or autofill) the password saved
in the password manager. The user gets a notification upon creation of this
passkey and is able to go to the password manager to manage it.
| **Note:** Other password managers may have their own conditions and notifications for this feature.

This feature requires version [1.6.0-alpha01](https://developer.android.com/jetpack/androidx/releases/credentials#1.6.0-alpha01) or higher.
| **Note:** Alpha software is subject to change and may be unstable.

## Add support for password management tools with passkey endpoints well-known URLs

For seamless integration and future compatibility with password and credential
management tools, we recommend adding support for passkey endpoints well-known
URLs. This is an open protocol for aligned parties to formally advertise their
support for passkeys and provide direct links for passkey enrollment and
management.

1. For a relying party at `https://example.com`, which has a website plus Android and iOS apps, the well-known URL would be `https://example.com/.well-known/passkey-endpoints`.
2. When the URL is queried, the response should use the following schema

       {
         "enroll": "https://example.com/account/manage/passkeys/create"
         "manage": "https://example.com/account/manage/passkeys"
       }

3. To have this link open directly in your app instead of on the web, use
   [Android app links](https://developer.android.com/training/app-links).

4. Further details can be found in the [passkey endpoints well-known URL](https://github.com/ms-id-standards/MSIdentityStandardsExplainers/blob/main/PasskeyEndpointsWellKnownUrl/explainer.md#example-1)
   explainer on GitHub.

## Help users manage their passkeys by showing which provider created them

One challenge users face when managing multiple passkeys associated with a given
app is identifying the correct passkey for editing or deletion. To assist with
this problem, it's recommended that apps and websites include additional
information like the provider that created the credential, the creation date and
the last-used date in a passkeys list on your app's settings screen.The provider
information is obtained by examining the [AAGUID](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API/Authenticator_data#attestedcredentialdata) associated
with the corresponding passkey. AAGUID can be found as part of a passkey's
authenticator data.

For example, if a user creates a passkey on an Android-powered device using
Google Password Manager, the RP then receives an AAGUID which looks something
like this: "ea9b8d66-4d01-1d21-3ce4-b6b48cb575d4". The relying party can
annotate the passkey in the passkey list to indicate that it was created using
Google Password Manager.

To map an AAGUID to a passkey provider, RPs can use [a community sourced
repository of AAGUIDs](https://github.com/passkeydeveloper/passkey-authenticator-aaguids). Look up the AAGUID on [the
list](https://github.com/passkeydeveloper/passkey-authenticator-aaguids/blob/main/aaguid.json) to find the passkey provider name and icon.

Read more about [AAGUID integration](https://web.dev/articles/webauthn-aaguid).

## Troubleshoot common errors

Refer to the [Credential Manager troubleshooting guide](https://developer.android.com/identity/sign-in/credential-manager-troubleshooting-guide) for common error
codes, descriptions, and information about their causes.

## Additional resources

To learn more about the Credential Manager API and passkeys, view the following
resources:

- [Passkeys UX Guide](https://developer.android.com/design/ui/mobile/guides/patterns/passkeys)
- [Video: How to reduce reliance on passwords in Android apps with passkey
  support](https://www.youtube.com/watch?v=36peNZUlgzU)
- [Codelab: Learn how to simplify auth journeys using Credential Manager API
  in your Android app](https://codelabs.developers.google.com/credential-manager-api-for-android#0)
- [Sample app: CredentialManager](https://github.com/android/identity-samples/tree/main/CredentialManager)