Restore Credentials
Android (Google)OfficialCreated by Google LLCDistributed by Android (Google)
- Skill
- Tool integration
- Software development
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a comprehensive guide for implementing the Android Restore Credentials feature. By leveraging the androidx.credentials library, developers can create, retrieve, and manage restore keys that allow users to sign in automatically when moving to a new device. The implementation follows a two-tier architecture, covering both background restoration via BackupAgent and foreground restoration in the main activity, ensuring a seamless user experience without requiring UI changes to existing authentication flows.
What it does
- Guides the creation of restore keys to enable silent sign-in on new devices.
- Details the two-tier restoration architecture for background and foreground recovery.
- Provides instructions for integrating the androidx.credentials library.
- Outlines mandatory security practices like clearing credentials upon sign-out.
- Explains how to handle restore key exceptions and cloud backup configurations.
- Supplies essential backend guidelines for managing restore keys on the server side.
When to use it
- When you want to improve user retention by enabling automatic sign-in on new devices.
- When your app uses the Credential Manager API and you wish to extend it with restoration capabilities.
- When you need to support seamless account migration across Android devices.
- When you are implementing or updating backup and restore logic for your application.
Advantages
- Enables a frictionless sign-in experience for users on new devices.
- Operates independently of primary authentication methods like passwords or passkeys.
- Requires no modifications to existing user-facing sign-in UI.
- Supports both cloud-backed and local-only restoration strategies.
Usage examples
- “How do I implement the two-tier restoration architecture for my Android app?”
- The agent will guide you through setting up background restoration in your BackupAgent and foreground restoration in your Launcher Activity, ensuring both tiers are correctly configured.
- “What are the steps to delete a restore key when a user logs out?”
- The agent will provide the code snippet to call clearCredentialState with TYPE_CLEAR_RESTORE_CREDENTIAL to ensure the key is removed from the device.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/android/restore-credentials/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip restore-credentials.zip -d .agents/skills
Documentation by Google LLC
Fundamentals
The objective is to implement the Restore Credentials feature through the
Android Credential Manager API (androidx.credentials). This allows apps that
use or are integrating Credential Manager to silently log users back in when
they restore their app on a new device. Restore Credentials operates
independently of the app's primary authentication method (passwords, passkeys,
federated sign-in) and requires no UI changes to existing sign-in flows.
Scope
Crucial: This skill focuses exclusively on the Android client-side integration. It does not implement the server-side cryptographic validation logic. The developer must be reminded of this and the Points to inform the developer about after implementation is done.
Implementation Guidelines
When instructed to implement Restore Credentials on a developer's application, remember the following:
Before the implementation, you MUST read and understand the Two-Tier Restoration Architecture and review the DOs and DON'Ts.
After the implementation, you MUST present the developer with the Backend Guidelines as a reminder for their backend setup. It is important that you remind the developer that they still have to implement the backend.
Two-Tier Restoration Architecture
To enable a resilient sign-in experience, retrieve credentials through a two-tier architecture:
Tier 1 (Primary - Background): Executes automatically during device setup using the app's
BackupAgent.onRestoreFinished()callback. This provides an invisible restoration before the user opens the app for the first time, allowing background sync and notification delivery.Tier 2 (Secondary - Foreground): Runs in the Launcher
Activity.onCreate()to catch failovers if background restoration didn't complete (example: dropped network, delayed restoration) or ifallowBackupis disabled.
If allowBackup in the manifest is set to true, implement both. Otherwise, only
implement tier 2 (Foreground Restoration). Do NOT change the value of
allowBackup in the manifest.
If you added a BackupAgent to the app, you MUST also set
android:fullBackupOnly="true" in the manifest. Do NOT do this if there
already existed a BackupAgent in the app before your implementation.
DOs and DON'Ts
DO:
Do check
AndroidManifest.xmlfor the value of allowBackup to determine what you have to implement.Do implement a fallback for createCredential: always try calling it first with
isCloudBackupEnabledset to true. If anE2eeUnavailableExceptionis thrown, catch it and retry the call withisCloudBackupEnabledset tofalse.Do implement a
BackupAgent(subclass ofandroid.app.backup.BackupAgent) ifallowBackupis true in the manifest.Do set
android:fullBackupOnly="true"in the manifest if you added aBackupAgentto the app.Call
clearCredentialState()when the user signs out. This is a mandatory security measure to log the user out fully.Do attempt to get the restore key on the first launch of the app on a new device and also within the
BackupAgent.onRestoreFinished()callback if your app uses it.Do ensure that a restore credential is created even if the user is already logged in.
Do ensure that the credential retrieval and login in
onRestoreFinished()is performed synchronously (for example usingrunBlocking).Do restore notifications in the
BackupAgentif your app uses them. (For example capture and send FCM token to backend)Do ensure that if you implement mock network requests or stubs, you replace all placeholders with valid, properly formatted JSON payloads for the credential requests.
Do encapsulate credential creation and retrieval into their own dedicated functions. Because credential creation must be called in multiple places (sign-up, sign-in) and retrieval across multiple tiers (
BackupAgentand LauncherActivity), this prevents code duplication.Do remind the developer of the critical guidelines for implementing the backend once you're done with the implementation.
Do generate a separate restore key for each application if the organization has multiple apps with different package names, as a restore key is tied to a unique application package name.
DON'T:
DON'T change the value of
allowBackupinAndroidManifest.xml. Restore Credentials functionality is not affected by the allowBackup setting, meaning the user will still be automatically logged in when a Restore Credential exists, even ifallowBackupis false.DON'T implement a
BackupAgentifallowBackupisfalseinAndroidManifest.xml.DON'T assume the credential stored in the
GetCredentialResponseto be of typePublicKeyCredential. It has typeRestoreCredential.DON'T chain
GetRestoreCredentialOptionwith any otherCredentialOptionin the construction of aGetCredentialRequest.DON'T assume
CredentialManageror the Android system will automatically delete a restore key when a user signs out of the app. You must explicitly callclearCredentialStatewith aClearCredentialStateRequestofTYPE_CLEAR_RESTORE_CREDENTIAL.DON'T remove any existing calls to
clearCredentialState(). AClearCredentialStateRequestwithout a type specified only clears all NON-restore credentials.
Implementation Guide
Implement the Android client-side code by using the following guide. Follow it step-by-step and don't implement any backend functionality, only remind the user of the Backend Guidelines once you're done.
Version compatibility
Credential Manager's Restore Credentials works on devices running Android 9 (API
level 28) and higher, Google Play services (GMS) core version 24220000 or
higher, and version 1.5.0 or higher of the androidx.credentials library.
Prerequisites
Set up a relying party server similar to the server for passkeys. If you already have a server set up to handle authentication with passkeys, use the same server-side implementation for restore keys.
[!NOTE] Note: While the server-side implementation is the same for passkeys and restore keys, your client-side app can support restore keys without supporting passkeys. Because restore keys work independently of the authentication method in your app (for example, passwords or Sign in with Google), you don't need to make any additional changes to the existing authentication methods in your app's code.
Dependencies
Add the following dependencies to your app module's build.gradle file:
Kotlin
dependencies {
implementation("androidx.credentials:credentials:1.7.0-alpha03")
implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")
}Groovy
dependencies {
implementation "androidx.credentials:credentials:1.7.0-alpha03"
implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha03"
}Restore Credentials is available from version 1.5.0 and higher of the androidx.credentials library. However, it's recommended to use the latest stable versions of the dependencies where possible.
[!NOTE] Note: The Restore Credentials feature works regardless of whether
allowBackupis set in the manifest.
Overview
Create a restore key: To create a restore key, complete the following steps:
Instantiate Credential Manager: Create a
CredentialManagerobject.Get credential creation options from the app server: Send the client app the details required to create the restore key from your app server.
Create the restore key: Create a restore key for the user's account if the user is signed in to your app.
Handle the credential creation response: Send the credentials from your client app to your app server for processing, and handle any exceptions.
Sign in with a restore key: To sign in with a restore key, complete the following steps:
Get credential retrieval options from the app server: Send the client app the details required to retrieve the restore key from your app server.
Get the restore key: Request the restore key from Credential Manager when the user sets up a new device. This lets the user sign in without additional input.
Handle the credential retrieval response: Send the restore key from the client app to the app server to sign in the user.
Delete a restore key.
Create a restore key
Your app should cover all cases of a user signing in to ensure active users have a restore key created. Create the restore key in the following scenarios:
If the user is signed in and a restore key isn't already created (such as in the
onCreatemethod for the mainActivity).When the user is signing in or completing a new account registration flow.
To optimize performance and avoid the overhead of creating or checking for a
restore credential on every single login, set a boolean flag or a credential
creation timestamp in local storage, such as has_synced_restore_credential, to
track whether the key has already been created.
[!NOTE] Note: A restore key is tied to an application's unique package name. If your organization's main app and sub-apps have different package names, create a separate restore key for each app.
Instantiate Credential Manager
Use your app's activity context to instantiate a CredentialManager object.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)Get credential creation options from your app server
Use a FIDO-compliant library in your app server to send your client app the information required to create the restore credential, such as information about the user, the app, and additional configuration properties. For more information about the server-side implementation, see Server-side guidance.
Create the restore key
After parsing the public key creation options sent by the server, create a
restore key by wrapping these options in a
CreateRestoreCredentialRequest object and calling the
createCredential() method with the CredentialManager object.
// createRestoreRequest contains the details sent by the server
val response = credentialManager.createCredential(context, createRestoreRequest)Key points about the code
The
CreateRestoreCredentialRequestobject contains the following fields:requestJson: The credential creation options sent by the app server in the Web Authentication API format forPublicKeyCredentialCreationOptionsJSON.isCloudBackupEnabled:Booleanfield to determine if the restore key should be backed up to the cloud. By default, this flag istrue. This field has these values:true: (Recommended) This value enables the backup of restore keys to the cloud if the user has Google Backup and end-to-end encryption, such as a screen lock, enabled.false: This value saves the key locally and not in the cloud. The key is not available on the new device if the user chooses to restore from the cloud.
[!CAUTION] Caution: It's recommended to set
isCloudBackupEnabledtotrue. If cloud backup is disabled and the user restores from a cloud backup, the call to retrieve the restore key fails. Users who restore your app with a cloud backup don't receive the restore key and aren't automatically signed in.
Handle the credential creation response
The Credential Manager API returns a response of type
CreateRestoreCredentialResponse. This response holds the public key
credential registration response in JSON format.
Send the public key from your app to the relying party server. This public key is similar to the public key generated when you create a passkey. The same code that handles passkey creation on the server can also handle restore key creation. For more information about the server-side implementation, see the guidance for passkeys.
During the restore key creation process, handle these exceptions:
CreateRestoreCredentialDomException: This exception occurs ifrequestJsonis invalid and does not follow the WebAuthn format forPublicKeyCredentialCreationOptionsJSON.E2eeUnavailableException: This exception occurs ifisCloudBackupEnabledistrue, but the user's device doesn't have data backup or end-to-end encryption, such as a screen lock.
To ensure that Restore Credentials are created in all cases, you must handle theE2eeUnavailableExceptionexplicitly by callingcreateCredentialwithisCloudBackupEnabledset totrue. IfE2eeUnavailableExceptionis thrown, catch and callcreateCredentialagain withisCloudBackupEnabledset tofalse.IllegalArgumentException: This exception occurs ifcreateRestoreRequestis empty or not valid JSON, or if it doesn't have a validuser.idthat conforms to the WebAuthn specifications.
Sign in with a restore key
Use Restore Credentials to silently sign in the user during the device setup process.
Get credential retrieval options from the app server
Send the client app the options required to get the restore key from the server. For similar passkey guidance for this step, see Sign in with a passkey. For more information about the server-side implementation, see the server-side authentication guide.
Get the restore key
To get the restore key on the new device, call the getCredential() method on
the CredentialManager object.
It's recommended to fetch the restore key in both of the following scenarios:
On the first launch of the app on the device. Credential restoration in this scenario is independent of restoration of the app data.
If app data backup and restore is enabled, get the restore key immediately after the app data is restored. Use
BackupAgentto configure your app's backup and ensure you complete thegetCredentialfunctionality within theonRestoreFinishedcallback. Don't use theonRestoremethod, as it is only called for key-value backups, whereasonRestoreFinishedis reliably called for any kind of backup restore. This avoids potential delays when users open their new device for the first time and lets users interact with the app without waiting for them to open your app. For example, this lets your app send the user notifications before they open the app for the first time on the new device, which is particularly relevant for messaging or communications apps.
If you create a new BackupAgent and previously had backup enabled with
allowBackup="true", set the boolean value android:fullBackupOnly="true" in
your app's manifest. This ensures that your app's backup and restore behavior is
maintained.
[!IMPORTANT] Important: Notifications aren't automatically restored after the restore credentials are retrieved. If you use Firebase to handle notifications, you must fetch and send the Firebase Cloud Messaging (FCM) token to the backend to successfully resume background messaging and notifications.
// Fetch the options required to get the restore key
val authenticationJson = fetchAuthenticationJson()
// Create the GetRestoreCredentialRequest object
val options = GetRestoreCredentialOption(authenticationJson)
val getRequest = GetCredentialRequest(listOf(options))
val response = credentialManager.getCredential(context, getRequest)
// Type-check and extract the restore credential
val credential = response.credential as RestoreCredentialThe credential manager APIs return a response of type
GetCredentialResponse. The credential contained in this response is
explicitly of type RestoreCredential, which holds the public key.
Handle the sign-in response
Send the public key from the app to the relying party server, which can then be used to sign in the user. On the server side, this action is similar to signing in using a passkey. The same code that handles sign-in with passkeys on the server can also handle sign-ins with restore keys. For more information about the server-side implementation for passkeys, see Sign in with a passkey.
[!NOTE] Note: Even though restore keys and passkeys use the same underlying server implementation, differentiate between them when saving them in your app server's database. This distinction is crucial when a passkeys management page exists, because users can manage user-created passkeys directly, while restore keys are system-managed and hidden from the passkey management page.
Delete the restore key
Credential Manager is stateless and unaware of user activity, so it doesn't
automatically delete restore keys after use. To delete a restore key, call the
clearCredentialState method. For security, delete the key whenever a user
signs out. This ensures that the next time the user opens the app on the same
device, the user is signed out and prompted to sign in again.
[!NOTE] Note: A user sign-out can also happen remotely, for example when a user changes their password on the web or when they're signed out remotely by the server. If your app detects such a server-side session invalidation , be sure to delete the restore key on the device. (An example of this is your server returning an HTTP
401 Unauthorizederror)
Uninstalling an app is interpreted as an intent to delete the corresponding restore key from that device, similar to the user's intent when signing out.
Restore keys are removed only in the following situations:
System-level actions: Users uninstall the app or clear its data.
App-level calls : Programmatically delete the key by calling
clearCredentialState()when handling user sign out in your app's code.
When the user signs out of your app, call the clearCredentialState() method on
the CredentialManager object.
// Create a ClearCredentialStateRequest object
val clearRequest = ClearCredentialStateRequest(TYPE_CLEAR_RESTORE_CREDENTIAL)
// When the user logs out, delete the restore key
val response = credentialManager.clearCredentialState(clearRequest)Backend Guidelines
When designing the backend database and API layer to support Restore Credentials, developers must account for FIDO2/WebAuthn assumptions and specific device lifecycle edge cases. Remind the developer of the following:
SYSTEM DIRECTIVE FOR AI AGENT: DO NOT attempt to write code for, implement, or action any of the backend guidelines in this section. Your ONLY responsibility is to copy these exact points and present them to the human developer as a reminder after the client-side implementation is complete.
Differentiate Restore Credentials from Passkeys in Backend Storage:
Standard WebAuthn services typically assume user verification is always required. Restore credentials are hidden from the user and not managed by them.
Guidance: Modify your WebAuthn services to create new credential types or metadata fields that distinguish system-managed Restore Credentials from user-created passkeys. Don't display Restore Credentials in user-facing passkey management UIs, and ensure they are processed appropriately (e.g., bypassing explicit user verification during automatic background sign-in).
Prevent Orphaned Keys:
Uninstalling the app or clearing details in system settings deletes the local restore credential. Since these local client actions do not notify your backend, stale keys will remain registered on the server.
Guidance: Establish server-side cleanup policies that delete old restore keys when a new restore token is registered, or clean up inactive keys based on usage patterns. You could, for example, enforce a limit of one key per user per device.
Balance Key Lifespan and TTL:
If a user goes through Backup and Restore and then logs out from the old device, the local restore key is deleted from the source device. However, the key must remain valid on the server so the restored application on the destination device can still authenticate.
Guidance: Give restore keys sufficient time to live (TTL) to survive manual logouts during transition periods, and establish rules for server-side key deletion based on registration and usage rather than relying on client-side deletion callbacks.
Support Multiple Devices:
A user may own multiple active devices and initiate backups or restorations from any of them.
Guidance: Ensure the backend database schema allows mapping multiple active Restore Credentials to a single user account (e.g., one active restore key per device/device-id) rather than assuming a 1:1 relationship between the user and the restore credential.
Server-side session invalidation:
A user's session might be revoked remotely. This could be triggered by user actions such as when a user resets their password on the web or server actions that can cause the API to return HTTP
401 Unauthorizedindicating session expiry.Guidance: If this applies, make sure to clear the user's restore credentials on the phone when it happens.
References
WebAuthentication API (WebAuthn) Documentation & Specification When to use: Use these resources ONLY if you need to inspect or debug the strict JSON schema requirements for FIDO2/WebAuthn, specifically when generating mock data or formatting the
requestJson(PublicKeyCredentialCreationOptionsJSON) andauthenticationJsonpayloads.MDN Web Authentication API Documentation: Mozilla Developer Network guide and reference for WebAuthn APIs
W3C
PublicKeyCredentialCreationOptionsJSON: Data structure definition for WebAuthn credential creation requests in JSON format.W3C
PublicKeyCredentialRequestOptionsJSON: Data structure definition for WebAuthn authentication or assertion requests in JSON format.
Files
- ATTRIBUTION.mdAdded by AutoGineer972 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md24.7 KiB
- references/android/guide/topics/manifest/application-element.md42.1 KiB
- references/android/identity/passkeys/create-passkeys.md19.0 KiB
- references/android/identity/passkeys/sign-in-with-passkeys.md11.3 KiB
references/android/identity/passkeys/create-passkeys.md
Before your users can authenticate with passkeys, your app must first register or create the passkey for their account.
To create the passkey, obtain details required to create the passkey from your app server, and then call the Credential Manager API, which returns a public and private key pair. The returned private key is stored in a credential provider, such as Google Password Manager, as a passkey. The public key is stored on your app server.
[!TIP] Tip: While designing authentication flows with passkeys, make sure that you follow the UX guidelines for passkeys.
Image: Passkeys are stored in a credential provider and public keys are stored on the app server **Figure 1:**Creation of passkeys
Prerequisites
Make sure that you have set up Digital Asset Links and that you target devices running Android 9 (API level 28) or higher.
Overview
This guide focuses on the changes required in your relying party client app to create a passkey, and gives a brief overview of the relying party app server implementation. To learn more about the server-side integration, see Server-side passkey registration.
Add dependencies to your app: Add the required Credential Manager libraries.
Instantiate Credential Manager: Create a Credential Manager instance.
Get credential creation options from the app server: From your app server, send the client app the details required to create the passkey, such as information about the app, the user, as well as a
challengeand other fields.Request a passkey: In your app, use the details received from the app server to create a
GetPublicKeyCredentialOptionobject and use this object to invoke thecredentialManager.getCredential()method to create a passkey.Handle the passkey creation response: When you receive the credentials on your client app, you must encode, serialize and then send the public key to the app server. You must also handle each of the exceptions that can occur in case of passkey creation.
Verify and save the public key on the server: Complete the server-side steps to verify the origin of the credential and then save the public key.
Notify the user: Notify the user that their passkey has been created.
[!TIP] Tip: To enhance the user experience during sign up, add functionality to restore credentials on a new device to let users seamlessly set up their existing accounts on new Android devices, and suppressing autofill dialogs on credential fields.
Add dependencies to your app
Add the following dependencies to your app module's build.gradle file:
Kotlin
dependencies {
implementation("androidx.credentials:credentials:1.7.0-alpha03")
implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")
}Groovy
dependencies {
implementation "androidx.credentials:credentials:1.7.0-alpha03"
implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha03"
}[!NOTE] Note: Use the latest available versions of the dependencies. Versions of
androidx.credentialsearlier than version 1.2 throw anUnsupportedOperationException("Post-U not supported yet")exception on Android 14.
Instantiate Credential Manager
Use your app or activity context to create a CredentialManager object.
// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)Get credential creation options from your app server
When the user clicks a "Create Passkey" button or when a new user signs up, make a request from your app to your app server to obtain the information required to start the passkey registration process.
Use a FIDO-compliant library in your app server to send your client app the information required to create a passkey, such as information about the user, the app, and additional configuration properties. To learn more, see Server side passkey registration.
In the client app, decode the public key creation options sent by the app server. These are usually represented in JSON format. To learn more about how this decoding is done for web clients, see Encoding and Decoding. For Android client apps, you must handle the decoding separately.
[!NOTE] Note: On your app server, securely store the
challengeso that you can later verify the origin of the credential.
The following snippet shows the structure the public key creation options sent by the app server:
{
"challenge": "<base64url-encoded challenge>",
"rp": {
"name": "<relying party name>",
"id": "<relying party host name>"
},
"user": {
"id": "<base64url-encoded user ID>",
"name": "<user name>",
"displayName": "<user display name>"
},
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7
}
],
"attestation": "none",
"excludeCredentials": [
{
"id": "<base64url-encoded credential ID to exclude>",
"type": "public-key"
}
],
"authenticatorSelection": {
"requireResidentKey": true,
"residentKey": "required",
"userVerification": "required"
}
}Key fields in the public key creation options include:
challenge: A server-generated random string that is used to prevent replay attacks.rp: Details about the app.rp.name: The app's name.rp.id: The app's domain or subdomain.
user: Details about the user.id: The user's unique ID. This value must not include personally identifying information, for example, email addresses or usernames. You can use a random, 16-byte value.name: A unique identifier for the account that the user will recognise, such as their email address or username. This will be displayed in the account selector. If using a username, use the same value as in password authentication.displayName: An optional, user-friendly name for the account intended for display in the account selector.
authenticatorSelection: Details about the device that will be used for authentication.authenticatorAttachment: Indicates the preferred authenticator. The possible values are as follows:platform: This value is used for an authenticator built into the user's device, such as a fingerprint sensor.cross-platform: This value is used for roaming devices such as security keys. It is not typically used in the passkey context.Unspecified (recommended): Leaving this value unspecified provides users with the flexibility to create passkeys on their preferred devices. In most cases, leaving the parameter unspecified is the best option.
requireResidentKey: To create a passkey, set the value of thisBooleanfield totrue.residentKey: To create a passkey, set the value torequired.userVerification: Used to specify the requirements for user verification during a passkey registration. The possible values are as follows:preferred: Use this value if you prioritize user experience over protection, such as in environments where user verification causes more friction than protection.required: Use this value if invoking a user verification method available on the device is required.discouraged: Use this value if using a user verification method is discouraged.
To learn more aboutuserVerification, see userVerification deep dive.
excludeCredentials: List credential IDs in an array to prevent the creation of a duplicate passkey if one already exists with the same credential provider.
Create a passkey
After you have parsed the server-side public key creation options, create a
passkey by wrapping these options in a CreatePublicKeyCredentialRequest object
and calling createCredential().
The createPublicKeyCredentialRequest includes the following:
requestJson: The credential creation options sent by the app server.preferImmediatelyAvailableCredentials: This is an optional Boolean field that defines whether to only use locally-available or credential provider-synced credentials to fulfill the request, instead of credentials from security keys or hybrid key flows. The possible usages are as follows:false(default): Use this value if the call to Credential Manager was triggered by an explicit user action.true: Use this value if Credential Manager is opportunistically called, such as when first opening the app.
If you set the value totrueand there are no immediately available credentials, Credential Manager won't show any UI and the request will fail immediately, returning NoCredentialException for get requests andCreateCredentialNoCreateOptionExceptionfor create requests.
origin: This field is automatically set for Android apps. For browsers and similarly privileged apps that need to setorigin, see Make Credential Manager calls on behalf of other parties for privileged apps.isConditional: This is an optional field that defaults tofalse. For more information, see Automatically create a passkey.
Calling the createCredential() function launches Credential Manager's built-in
bottom sheet UI that prompts the user to use a passkey and to select a
credential provider and account for storage. However, if isConditional is set
to true, the bottom sheet UI does not display, and the passkey is
automatically created.
Automatically create a passkey
You can automatically create a passkey for a user after a successful password
login by setting the isConditional parameter to true in your
CreatePublicKeyCredentialRequest while creating a passkey. If the user doesn't
already have a passkey, your app will automatically attempt to create one in the
background and store it in the user's credential provider, such as Google
Password Manager. For an example of how this is implemented, see the public
sample.
Image: An example of the notification Google Password Manager shows after passkey creation **Figure 2:**Google Password Manager notification
[!NOTE] Note: If a passkey is created automatically, credential providers are responsible for notifying users about a newly created passkey. Google Password Manager notifies users when a passkey is automatically created. However, other credential providers might have their own conditions and notifications for this feature.
Handle the response
After the user is verified using the device's screen lock, a passkey is created and stored in the user's selected credential provider.
The response after you successfully call createCredential() is a
PublicKeyCredential object.
The PublicKeyCredential looks as follows:
{
"id": "<identifier>",
"type": "public-key",
"rawId": "<identifier>",
"response": {
"clientDataJSON": "<ArrayBuffer encoded object with the origin and signed challenge>",
"attestationObject": "<ArrayBuffer encoded object with the public key and other information.>"
},
"authenticatorAttachment": "platform"
}In the client app, serialize the object and send it to the app server.
Add code to handle failures as shown in the following snippet:
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}")
}
}Verify and save the public key on the app server
On the app server, you must verify the public key credential and then save the public key.
To verify the public key credential's origin, compare it against an allow list of approved apps. If a key has an unrecognized origin, reject it.
[!NOTE] Note: An app's origin is based on its unique identity, which is the SHA-256 fingerprint of its signing certificate.
To obtain the app's SHA 256 fingerprint:
Print your release app's signing certificate by running the following command in a terminal:
keytool -list -keystore <path-to-apk-signing-keystore>In the response, identify the signing certificate's SHA 256 fingerprint, mentioned as
Certificate fingerprints block:SHA256.Encode the SHA256 fingerprint with base64url encoding. This Python example demonstrates how to properly encode the fingerprint:
import binascii import base64 fingerprint = '<SHA256 finerprint>' # your app's SHA256 fingerprint print(base64.urlsafe_b64encode(binascii.a2b_hex(fingerprint.replace(':', ''))).decode('utf8').replace('=', ''))Append
android:apk-key-hash: to the start of the output from the previous step so that you get something that is similar to the following:android:apk-key-hash:<encoded SHA 256 fingerprint>The result should match with an allowed origin on your app server. If you have multiple signing certificates, such as certificates for debugging and release, or multiple apps, then repeat the process and accept all the origins as valid on the app server.
[!NOTE] Note: When you save the passkey on the app server, make sure that you save the Authenticator Attestation Globally Unique Identifier (AAGUID) from the client data. The AAGUID is a unique number that identifies the model of the authenticator. For more information, see Manage passkeys.
Notify the user
After the passkey is successfully created, notify your users about the passkey and inform them that they can manage their passkeys from their credential provider app or from within the app settings. Notify users by using a custom dialog, notification, or snackbar. Since an unexpected passkey creation by a malicious entity requires an immediate security alert, consider supplementing these in-app methods with external communication, such as an email.
Enhance the user experience
To enhance the user experience while implementing sign up with Credential Manager, consider adding functionality for restore credentials and suppress autofill dialogs.
Add functionality to restore credentials on a new device
To allow users to seamlessly log into their accounts on a new device, implement
the Restore Credentials functionality. Adding restore credentials with
BackupAgent logs users in when they open your restored app on a new device,
letting them use your app right away.
Suppress autofill on credential fields (optional)
For app screens where users are expected to use Credential Manager's bottom
sheet UI for authentication, add the isCredential attribute to the username
and password fields. This suppresses autofill dialogs (FillDialog and
SaveDialog) from overlapping with Credential Manager's bottom sheet UI.
The isCredential attribute is supported on Android 14 and higher.
The following example demonstrates how you can add the isCredential attribute
to the relevant username and password fields in the relevant views for your app:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isCredential="true" /\>Next steps
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Google LLC
- Publisher
- Android (Google) (Official)
- Distributed by
- Android (Google)
- Source
- android/skills · identity/restore-credentials · commit bf68e2d
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.txt)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Google LLC or Android (Google).
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download restore-credentials.zip