restore-credentials

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

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.
本内容旨在通过Android Credential Manager API(
androidx.credentials
)实现Restore Credentials功能。这使得使用或集成Credential Manager的应用,在用户将应用恢复到新设备时,能够自动为用户静默登录。Restore Credentials独立于应用的主要认证方式(密码、通行密钥、联合登录),无需对现有登录流程的UI进行任何修改。

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.
重要提示: 本技能仅聚焦于Android客户端集成,不实现服务端的加密验证逻辑。必须提醒开发者这一点,并在完成实现后告知其需要注意的要点。

Implementation Guidelines

实施指南

When instructed to implement Restore Credentials on a developer's application, remember the following:
  1. Before the implementation, you MUST read and understand the Two-Tier Restoration Architecture and review the DOs and DON'Ts.
  2. 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.
当被要求在开发者的应用中实现Restore Credentials时,请牢记以下事项:
  1. 在开始实施前,你必须阅读并理解双层恢复架构,同时查看注意事项(DOs and DON'Ts)。
  2. 完成实施后,你必须向开发者展示后端指南,提醒他们进行后端配置。务必告知开发者仍需自行实现后端功能。

Two-Tier Restoration Architecture

双层恢复架构

To enable a resilient sign-in experience, retrieve credentials through a two-tier architecture:
  1. 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.
  2. 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 if
    allowBackup
    is 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.
为实现可靠的登录体验,请通过双层架构获取凭证:
  1. 第一层(主层 - 后台): 在设备设置期间,通过应用的
    BackupAgent.onRestoreFinished()
    回调自动执行。这能在用户首次打开应用前完成隐形恢复,支持后台同步和通知推送。
  2. 第二层(次层 - 前台): 在启动器
    Activity.onCreate()
    中运行,用于捕获后台恢复未完成的情况(例如:网络中断、恢复延迟)或
    allowBackup
    被禁用的场景。
如果清单文件中的
allowBackup
设置为true,则需同时实现两层架构;否则,仅实现第二层(前台恢复)。请勿修改清单文件中
allowBackup
的值。

DOs and DON'Ts

注意事项(DOs and DON'Ts)

DO:
  • Do check
    AndroidManifest.xml
    for the value of allowBackup to determine what you have to implement.
  • Do implement a fallback for createCredential: always try calling it first with
    isCloudBackupEnabled
    set to true. If an
    E2eeUnavailableException
    is thrown, catch it and retry the call with
    isCloudBackupEnabled
    set to
    false
    .
  • Do implement a
    BackupAgent
    (subclass of
    android.app.backup.BackupAgent
    ) if
    allowBackup
    is true in the manifest.
  • 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 using
    runBlocking
    ).
  • Do restore notifications in the
    BackupAgent
    if 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 (
    BackupAgent
    and Launcher
    Activity
    ), 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
    allowBackup
    in
    AndroidManifest.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 if
    allowBackup
    is false.
  • DON'T implement a
    BackupAgent
    if
    allowBackup
    is
    false
    in
    AndroidManifest.xml
    .
  • DON'T assume the credential stored in the
    GetCredentialResponse
    to be of type
    PublicKeyCredential
    . It has type
    RestoreCredential
    .
  • DON'T chain
    GetRestoreCredentialOption
    with any other
    CredentialOption
    in the construction of a
    GetCredentialRequest
    .
  • DON'T assume
    CredentialManager
    or the Android system will automatically delete a restore key when a user signs out of the app. You must explicitly call
    clearCredentialState
    with a
    ClearCredentialStateRequest
    of
    TYPE_CLEAR_RESTORE_CREDENTIAL
    .
  • DON'T remove any existing calls to
    clearCredentialState()
    . A
    ClearCredentialStateRequest
    without a type specified only clears all NON-restore credentials.
应当执行:
  • 检查
    AndroidManifest.xml
    中的allowBackup值,以确定需要实现的内容。
  • 为createCredential实现回退逻辑:始终先尝试将
    isCloudBackupEnabled
    设为true调用该方法。如果抛出
    E2eeUnavailableException
    ,捕获该异常并将
    isCloudBackupEnabled
    设为
    false
    后重试。
  • 如果清单文件中的allowBackup为true,实现
    BackupAgent
    (继承自
    android.app.backup.BackupAgent
    )。
  • 用户退出登录时调用
    clearCredentialState()
    ,这是确保用户完全退出的强制性安全措施。
  • 在新设备上首次启动应用时尝试获取恢复密钥;如果应用使用了
    BackupAgent
    ,还需在
    BackupAgent.onRestoreFinished()
    回调中执行该操作。
  • 确保即使用户已登录,也会创建恢复凭证。
  • 确保
    onRestoreFinished()
    中的凭证获取和登录操作同步执行(例如使用
    runBlocking
    )。
  • 如果应用使用通知功能,需在
    BackupAgent
    中恢复通知(例如捕获并将FCM令牌发送到后端)。
  • 如果实现模拟网络请求或存根,需将所有占位符替换为格式正确的有效JSON负载,用于凭证请求。
  • 将凭证创建和获取逻辑封装到独立的专用函数中。由于凭证创建需要在多个场景(注册、登录)调用,而获取操作需要在多个层级(
    BackupAgent
    和启动器
    Activity
    )执行,这样可以避免代码重复。
  • 完成客户端实现后,提醒开发者注意后端实施的关键指南。
  • 如果组织拥有多个不同包名的应用,需为每个应用生成独立的恢复密钥,因为恢复密钥与唯一的应用包名绑定。
禁止执行:
  • 请勿修改
    AndroidManifest.xml
    中的
    allowBackup
    值。Restore Credentials功能不受allowBackup设置影响,这意味着即使
    allowBackup
    为false,只要存在恢复凭证,用户仍会自动登录。
  • 如果
    AndroidManifest.xml
    中的allowBackup为
    false
    ,请勿实现
    BackupAgent
    。
  • 请勿假设
    GetCredentialResponse
    中存储的凭证类型为
    PublicKeyCredential
    ,其实际类型为
    RestoreCredential
    。
  • 在构建
    GetCredentialRequest
    时,请勿将
    GetRestoreCredentialOption
    与其他
    CredentialOption
    链式调用。
  • 请勿假设Credential Manager或Android系统会在用户退出应用时自动删除恢复密钥。你必须显式调用
    clearCredentialState
    并传入类型为
    TYPE_CLEAR_RESTORE_CREDENTIAL
    的
    ClearCredentialStateRequest
    。
  • 请勿移除任何现有的
    clearCredentialState()
    调用。未指定类型的
    ClearCredentialStateRequest
    仅会清除所有非恢复凭证。

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.
按照以下指南实现Android客户端代码,请逐步执行,不要实现任何后端功能,仅需在完成后提醒用户查看后端指南。

Version compatibility

版本兼容性

Credential Manager's Restore Credentials works on devices running Android 9 and higher, Google Play services (GMS) core version 24220000 or higher, and version 1.5.0 or higher of the
androidx.credentials
library.
Credential Manager的Restore Credentials功能适用于运行Android 9及以上版本、Google Play服务(GMS)核心版本24220000及以上,以及
androidx.credentials
库1.5.0及以上版本的设备。

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.
搭建一个依赖方服务器,其功能与通行密钥的服务器类似。如果已经搭建了处理通行密钥认证的服务器,可使用相同的服务端实现来处理恢复密钥。
[!NOTE] 注意: 虽然通行密钥和恢复密钥的服务端实现相同,但客户端应用可以在不支持通行密钥的情况下支持恢复密钥。由于恢复密钥独立于应用中的认证方式(例如密码或Google登录),你无需对应用代码中现有的认证方式进行任何额外修改。

Dependencies

依赖配置

Add the following dependencies to your app module's
build.gradle
file:
将以下依赖项添加到应用模块的
build.gradle
文件中:

Kotlin

Kotlin

kotlin
dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha03")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")
}
kotlin
dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha03")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")
}

Groovy

Groovy

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
allowBackup
is set in the
manifest
.
groovy
dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha03"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha03"
}
Restore Credentials功能从androidx.credentials库1.5.0版本开始可用,但建议尽可能使用最新的稳定版本依赖。
[!NOTE] 注意: Restore Credentials功能的可用性与清单文件中是否设置
allowBackup
无关。

Overview

流程概述

  1. Create a restore key: To create a restore key, complete the following steps:
    1. Instantiate Credential Manager: Create a
      CredentialManager
      object.
    2. Get credential creation options from the app server: Send the client app the details required to create the restore key from your app server.
    3. Create the restore key: Create a restore key for the user's account if the user is signed in to your app.
    4. Handle the credential creation response: Send the credentials from your client app to your app server for processing, and handle any exceptions.
  2. Sign in with a restore key: To sign in with a restore key, complete the following steps:
    1. Get credential retrieval options from the app server: Send the client app the details required to retrieve the restore key from your app server.
    2. 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.
    3. Handle the credential retrieval response: Send the restore key from the client app to the app server to sign in the user.
  3. Delete a restore key.
  1. 创建恢复密钥:创建恢复密钥需完成以下步骤:
    1. 实例化Credential Manager:创建
      CredentialManager
      对象。
    2. 从应用服务器获取凭证创建选项:从应用服务器获取创建恢复密钥所需的详细信息并发送给客户端应用。
    3. 创建恢复密钥:如果用户已登录应用,为其账户创建恢复密钥。
    4. 处理凭证创建响应:将客户端应用的凭证发送到应用服务器进行处理,并处理可能出现的异常。
  2. 使用恢复密钥登录:使用恢复密钥登录需完成以下步骤:
    1. 从应用服务器获取凭证检索选项:从应用服务器获取检索恢复密钥所需的详细信息并发送给客户端应用。
    2. 获取恢复密钥:用户设置新设备时,向Credential Manager请求恢复密钥,实现用户无需额外输入即可登录。
    3. 处理凭证检索响应:将客户端应用的恢复密钥发送到应用服务器,完成用户登录。
  3. 删除恢复密钥。

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
    onCreate
    method for the main
    Activity
    ).
  • 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.
应用需覆盖用户登录的所有场景,确保活跃用户都能创建恢复密钥。请在以下场景中创建恢复密钥:
  • 用户已登录但尚未创建恢复密钥时(例如在主
    Activity
    的
    onCreate
    方法中)。
  • 用户登录或完成新账户注册流程时。
为优化性能,避免每次登录都创建或检查恢复凭证的开销,可在本地存储中设置一个布尔标志或凭证创建时间戳,例如
has_synced_restore_credential
,用于跟踪密钥是否已创建。
[!NOTE] 注意: 恢复密钥与应用的唯一包名绑定。如果组织的主应用和子应用具有不同的包名,需为每个应用创建独立的恢复密钥。

Instantiate Credential Manager

实例化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)
使用应用的活动上下文实例化
CredentialManager
对象。
// 使用应用或活动上下文实例化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.
在应用服务器中使用符合FIDO标准的库,向客户端应用发送创建恢复凭证所需的信息,例如用户信息、应用信息和其他配置属性。有关服务端实现的更多信息,请查看服务端指南。

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)
解析服务器发送的公钥创建选项后,将这些选项包装到
CreateRestoreCredentialRequest
对象中,并调用
CredentialManager
对象的
createCredential()
方法,以此创建恢复密钥。
// createRestoreRequest包含服务器发送的详细信息
val response = credentialManager.createCredential(context, createRestoreRequest)

Key points about the code

代码要点

  • The
    CreateRestoreCredentialRequest
    object contains the following fields:
    • requestJson
      : The credential creation options sent by the app server in the Web Authentication API format for
      PublicKeyCredentialCreationOptionsJSON
      .
    • isCloudBackupEnabled
      :
      Boolean
      field to determine if the restore key should be backed up to the cloud. By default, this flag is
      true
      . 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 is recommended to set
    isCloudBackupEnabled
    to
    true
    . 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 are not automatically signed in.
  • CreateRestoreCredentialRequest
    对象包含以下字段:
    • requestJson
      :应用服务器发送的凭证创建选项,采用Web Authentication API格式的
      PublicKeyCredentialCreationOptionsJSON
      。
    • isCloudBackupEnabled
      :布尔字段,用于确定恢复密钥是否应备份到云端。默认值为
      true
      ,该字段的取值说明如下:
      • true
        :(推荐)如果用户启用了Google备份和端到端加密(例如屏幕锁定),此值会将恢复密钥备份到云端。
      • false
        :此值会将密钥保存在本地而非云端。如果用户选择从云端恢复应用,该密钥将无法在新设备上使用。
    [!CAUTION] 警告: 建议将
    isCloudBackupEnabled
    设为
    true
    。如果云端备份被禁用,且用户从云端恢复应用,获取恢复密钥的调用将失败。通过云端恢复应用的用户将无法获取恢复密钥,也无法自动登录。

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 if
    requestJson
    is invalid and does not follow the WebAuthn format for
    PublicKeyCredentialCreationOptionsJSON
    .
  • E2eeUnavailableException
    : This exception occurs if
    isCloudBackupEnabled
    is
    true
    , but the user's device does not 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 the
    E2eeUnavailableException
    explicitly by calling
    createCredential
    with
    isCloudBackupEnabled
    set to
    true
    . If
    E2eeUnavailableException
    is thrown, catch and call
    createCredential
    again with
    isCloudBackupEnabled
    set to
    false
    .
  • IllegalArgumentException
    : This exception occurs if
    createRestoreRequest
    is empty or not valid JSON, or if it does not have a valid
    user.id
    that conforms to the WebAuthn specifications.
Credential Manager API返回类型为
CreateRestoreCredentialResponse
的响应,该响应以JSON格式存储公钥凭证注册响应。
将应用中的公钥发送到依赖方服务器,该公钥与创建通行密钥时生成的公钥类似。服务器上处理通行密钥创建的代码同样可用于处理恢复密钥创建。有关服务端实现的更多信息,请查看通行密钥指南。
在恢复密钥创建过程中,需处理以下异常:
  • CreateRestoreCredentialDomException
    :如果
    requestJson
    无效且不符合WebAuthn格式的
    PublicKeyCredentialCreationOptionsJSON
    ,会抛出此异常。
  • E2eeUnavailableException
    :如果
    isCloudBackupEnabled
    设为
    true
    ,但用户设备未启用数据备份或端到端加密(例如屏幕锁定),会抛出此异常。
    为确保在所有场景下都能创建Restore Credentials,必须显式处理
    E2eeUnavailableException
    :先将
    isCloudBackupEnabled
    设为
    true
    调用
    createCredential
    ,如果抛出
    E2eeUnavailableException
    ,捕获该异常并将
    isCloudBackupEnabled
    设为
    false
    后再次调用
    createCredential
    。
  • IllegalArgumentException
    :如果
    createRestoreRequest
    为空或不是有效的JSON,或者没有符合WebAuthn规范的有效
    user.id
    ,会抛出此异常。

Sign in with a restore key

使用恢复密钥登录

Use Restore Credentials to silently sign in the user during the device setup process.
使用Restore Credentials在设备设置过程中为用户静默登录。

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 is 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
    BackupAgent
    to configure your app's backup and ensure you complete the
    getCredential
    functionality within the
    onRestoreFinished
    callback. Don't use the
    onRestore
    method, as it is only called for key-value backups, whereas
    onRestoreFinished
    is 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.
[!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 RestoreCredential
The 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.
要在新设备上获取恢复密钥,调用
CredentialManager
对象的
getCredential()
方法。
建议在以下两种场景中获取恢复密钥:
  • 设备上首次启动应用时。此场景下的凭证恢复独立于应用数据恢复。
  • 如果启用了应用数据备份和恢复,在应用数据恢复完成后立即获取恢复密钥。使用
    BackupAgent
    配置应用备份,并确保在
    onRestoreFinished
    回调中完成
    getCredential
    功能。请勿使用
    onRestore
    方法,因为它仅针对键值备份调用,而
    onRestoreFinished
    会在任何类型的备份恢复完成后可靠调用。这样可以避免用户首次打开新设备时可能出现的延迟,让用户无需等待即可与应用交互。例如,这能让应用在用户首次打开新设备上的应用前就向其发送通知,这对消息类或通讯类应用尤为重要。
[!IMPORTANT] 重要提示: 获取恢复凭证后,通知不会自动恢复。如果使用Firebase处理通知,必须获取并将Firebase Cloud Messaging(FCM)令牌发送到后端,才能成功恢复后台消息和通知。
// 获取获取恢复密钥所需的选项
val authenticationJson = fetchAuthenticationJson()

// 创建GetRestoreCredentialRequest对象
val options = GetRestoreCredentialOption(authenticationJson)
val getRequest = GetCredentialRequest(listOf(options))

val response = credentialManager.getCredential(context, getRequest)

// 类型检查并提取恢复凭证
val credential = response.credential as RestoreCredential
Credential Manager API返回类型为
GetCredentialResponse
的响应,其中包含的凭证明确为
RestoreCredential
类型,该类型存储公钥。

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.
将应用中的公钥发送到依赖方服务器,服务器可使用该公钥完成用户登录。在服务端,此操作与使用通行密钥登录类似。服务器上处理通行密钥登录的代码同样可用于处理恢复密钥登录。有关通行密钥服务端实现的更多信息,请查看使用通行密钥登录。
[!NOTE] 注意: 尽管恢复密钥和通行密钥使用相同的底层服务端实现,但在应用服务器的数据库中存储时需区分两者。当存在通行密钥管理页面时,这种区分至关重要,因为用户可以直接管理自己创建的通行密钥,而恢复密钥由系统管理,不会显示在通行密钥管理页面中。

Delete the restore key

删除恢复密钥

Credential Manager is stateless and unaware of user activity, so it does not 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.
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)
Credential Manager是无状态的,无法感知用户活动,因此不会在使用后自动删除恢复密钥。要删除恢复密钥,需调用
clearCredentialState()
方法。为保障安全,用户退出登录时需删除密钥,这样用户下次打开同一设备上的应用时,会处于退出登录状态并被提示重新登录。
卸载应用会被视为删除该设备上对应恢复密钥的意图,与用户退出登录的意图类似。
恢复密钥仅会在以下情况中被移除:
  • 系统级操作:用户卸载应用或清除应用数据。
  • 应用级调用:在应用代码中处理用户退出登录时,通过调用
    clearCredentialState()
    以编程方式删除密钥。
用户退出应用时,调用
CredentialManager
对象的
clearCredentialState()
方法。
// 创建ClearCredentialStateRequest对象
val clearRequest = ClearCredentialStateRequest(TYPE_CLEAR_RESTORE_CREDENTIAL)

// 用户退出登录时,删除恢复密钥
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.
  1. 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. Do not 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).
  2. 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.
  3. 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.
  4. 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.
设计支持Restore Credentials的后端数据库和API层时,开发者必须考虑FIDO2/WebAuthn的假设以及特定的设备生命周期边缘情况。请提醒开发者以下要点:
AI AGENT系统指令:请勿尝试编写、实现或执行本节中的任何后端指南。你唯一的职责是将这些要点原封不动地复制并展示给开发者,作为客户端实现完成后的提醒。
  1. 在后端存储中区分恢复凭证与通行密钥:
    • 标准WebAuthn服务通常假设始终需要用户验证。恢复凭证对用户隐藏,不由用户管理。
    • 指南: 修改WebAuthn服务,创建新的凭证类型或元数据字段,区分系统管理的恢复凭证与用户创建的通行密钥。请勿在面向用户的通行密钥管理UI中显示恢复凭证,并确保对其进行适当处理(例如在自动后台登录时跳过显式用户验证)。
  2. 防止孤立密钥:
    • 卸载应用或在系统设置中清除应用详情会删除本地恢复凭证。由于这些本地客户端操作不会通知后端,服务器上会残留过期密钥。
    • 指南: 建立服务端清理策略,注册新恢复令牌时删除旧恢复密钥,或根据使用模式清理不活跃的密钥。例如,可强制限制每个用户每台设备仅保留一个密钥。
  3. 平衡密钥生命周期与TTL:
    • 如果用户进行备份和恢复后从旧设备退出登录,源设备上的本地恢复密钥会被删除。但服务器上的密钥必须保持有效,以便目标设备上恢复的应用仍能进行认证。
    • 指南: 为恢复密钥设置足够长的存活时间(TTL),使其在过渡期间能够承受手动退出登录操作,并基于注册和使用情况建立服务端密钥删除规则,而非依赖客户端删除回调。
  4. 支持多设备:
    • 用户可能拥有多台活跃设备,并可从任意设备发起备份或恢复操作。
    • 指南: 确保后端数据库架构允许将多个活跃恢复凭证映射到单个用户账户(例如每个设备/设备ID对应一个活跃恢复密钥),而非假设用户与恢复凭证之间是1:1的关系。

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
    ) and
    authenticationJson
    payloads.
  • 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.
  • WebAuthentication API(WebAuthn)文档与规范 使用场景: 仅当你需要检查或调试FIDO2/WebAuthn的严格JSON schema要求时使用这些资源,特别是生成模拟数据或格式化
    requestJson
    (
    PublicKeyCredentialCreationOptionsJSON
    )和
    authenticationJson
    负载时。
  • MDN Web Authentication API文档:Mozilla开发者网络提供的WebAuthn API指南与参考
  • W3C
    PublicKeyCredentialCreationOptionsJSON
    :WebAuthn凭证创建请求的JSON格式数据结构定义
  • W3C
    PublicKeyCredentialRequestOptionsJSON
    :WebAuthn认证或断言请求的JSON格式数据结构定义