使用 Credential Manager 實作還原憑證功能

本頁面說明如何建立、登入及刪除還原金鑰。

版本相容性

Credential Manager 的還原憑證功能適用於搭載 Android 9 (API 級別 28) 以上版本的裝置、Google Play 服務 (GMS) 核心 24220000 以上版本,以及 androidx.credentials 程式庫 1.5.0 以上版本。

必要條件

設定依賴方伺服器,類似於密碼金鑰的伺服器。如果您已設定伺服器來處理密碼金鑰驗證,請使用相同的伺服器端實作來還原金鑰。

依附元件

在應用程式模組的 build.gradle 檔案中新增下列依附元件:

Kotlin

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

Groovy

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha02"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha02"
}

還原憑證適用於 androidx.credentials 程式庫 1.5.0 以上版本。不過,建議您盡可能使用最新穩定版本的依附元件。

總覽

  1. 建立還原金鑰:如要建立還原金鑰,請完成下列步驟:
    1. 例項化 Credential Manager:建立 CredentialManager 物件。
    2. 從應用程式伺服器取得憑證建立選項:將從應用程式伺服器建立還原金鑰所需的詳細資料傳送至用戶端應用程式。
    3. 建立還原金鑰:如果使用者已登入應用程式,請為使用者帳戶建立還原金鑰。
    4. 處理憑證建立回應:將憑證從用戶端應用程式傳送至應用程式伺服器進行處理,並處理任何例外狀況。
  2. 使用還原金鑰登入:如要使用還原金鑰登入,請完成下列步驟:
    1. 從應用程式伺服器取得憑證擷取選項:將從應用程式伺服器擷取還原金鑰所需的詳細資料,傳送至用戶端應用程式。
    2. 取得還原金鑰:使用者設定新裝置時,向 Credential Manager 要求還原金鑰。這樣一來,使用者不必輸入其他資訊即可登入。
    3. 處理憑證擷取回應:將還原金鑰從用戶端應用程式傳送至應用程式伺服器,為使用者登入。
  3. 刪除還原金鑰。

建立還原金鑰

應用程式應涵蓋使用者登入的所有情況,確保活躍使用者已建立還原金鑰。在下列情況下,請建立還原金鑰:

  • 如果使用者已登入,且尚未建立還原金鑰 (例如在主要 Activity 的 onCreate 方法中)。
  • 使用者登入或完成新帳戶註冊流程時。

為發揮最佳效能,並避免每次登入時建立或檢查還原憑證的負擔,請在本機儲存空間 (例如 has_synced_restore_credential) 設定 boolean 旗標或憑證建立時間戳記,追蹤是否已建立金鑰。

例項化 Credential Manager

使用應用程式的活動情境,將 CredentialManager 物件例項化。

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

從應用程式伺服器取得憑證建立選項

在應用程式伺服器中使用符合 FIDO 規範的程式庫,將建立還原憑證所需的資訊傳送至用戶端應用程式,例如使用者、應用程式和額外設定屬性的相關資訊。如要進一步瞭解伺服器端導入,請參閱伺服器端指南。

建立還原金鑰

剖析伺服器傳送的公開金鑰建立選項後,請將這些選項包裝在 CreateRestoreCredentialRequest 物件中,並使用 CredentialManager 物件呼叫 createCredential() 方法,建立還原金鑰。

// createRestoreRequest contains the details sent by the server 
val response = credentialManager.createCredential(context, createRestoreRequest)

程式碼重點

  • CreateRestoreCredentialRequest 物件包含下列欄位:

    • requestJson:應用程式伺服器以 Web Authentication API 格式傳送的憑證建立選項,用於 PublicKeyCredentialCreationOptionsJSON。
    • isCloudBackupEnabled:Boolean 欄位,用於判斷是否應將還原金鑰備份到雲端。根據預設,這個旗標為 true。這個欄位的值如下:

      • true:(建議) 如果使用者已啟用 Google 備份和端對端加密 (例如螢幕鎖定),這個值會啟用還原金鑰備份至雲端的功能。
      • false:這個值會將金鑰儲存在本機,而非雲端。如果使用者選擇從雲端還原,新裝置上就無法使用該金鑰。

處理憑證建立回應

Credential Manager API 會傳回 CreateRestoreCredentialResponse 類型的回應。這項回應包含 JSON 格式的公開金鑰憑證註冊回應。

將應用程式的公開金鑰傳送至依賴方伺服器。這個公開金鑰與建立密碼金鑰時產生的公開金鑰類似。在伺服器上處理密碼金鑰建立作業的程式碼,也可以處理還原金鑰建立作業。如要進一步瞭解伺服器端實作,請參閱密碼金鑰指南。

在建立還原金鑰的過程中,請處理下列例外狀況:

  • CreateRestoreCredentialDomException:如果 requestJson 無效,且不符合 PublicKeyCredentialCreationOptionsJSON 的 WebAuthn 格式,就會發生這個例外狀況。
  • E2eeUnavailableException:如果 isCloudBackupEnabled 為 true,但使用者的裝置沒有資料備份或端對端加密 (例如螢幕鎖定),就會發生這個例外狀況。
    為確保在所有情況下都能建立還原憑證,您必須明確處理 E2eeUnavailableException,方法是呼叫 createCredential,並將 isCloudBackupEnabled 設為 true。如果擲回 E2eeUnavailableException,請擷取並再次呼叫 createCredential,並將 isCloudBackupEnabled 設為 false。
  • IllegalArgumentException:如果 createRestoreRequest 為空白或不是有效的 JSON,或沒有符合 WebAuthn 規格的有效 user.id,就會發生這個例外狀況。

使用還原金鑰登入

在裝置設定程序中,使用 Restore Credentials API 讓使用者自動登入。

從應用程式伺服器取得憑證擷取選項

將從伺服器取得還原金鑰所需的選項,傳送至用戶端應用程式。如需這個步驟的類似密碼金鑰指南,請參閱「使用密碼金鑰登入」。如要進一步瞭解伺服器端導入作業,請參閱伺服器端驗證指南。

取得還原金鑰

如要在新裝置上取得還原金鑰,請呼叫 CredentialManager 物件的 getCredential() 方法。

建議您在下列兩種情況下擷取還原金鑰:

  • 在裝置上首次啟動應用程式時。在這種情況下,憑證還原與應用程式資料還原無關。
  • 如果已啟用應用程式資料備份和還原功能,請在還原應用程式資料後立即取得還原金鑰。使用 BackupAgent 設定應用程式的備份,並確保在 onRestoreFinished 回呼中完成 getCredential 功能。請勿使用 onRestore 方法,因為系統只會針對鍵/值備份呼叫該方法,而 onRestoreFinished 則會針對任何類型的備份還原呼叫。這樣一來,使用者首次開啟新裝置時,就不會發生延遲,而且不必等待應用程式開啟,就能與應用程式互動。舉例來說,應用程式可以在使用者首次在新裝置上開啟應用程式之前,傳送通知給使用者,這對訊息或通訊應用程式來說特別重要。

如果您建立新的 BackupAgent,且先前已使用 allowBackup="true" 啟用備份功能,請在應用程式資訊清單中設定布林值 android:fullBackupOnly="true"。這可確保應用程式的備份和還原行為維持不變。

// 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

Credential Manager API 會傳回 GetCredentialResponse 類型的回應。這項回應中的憑證明確屬於 RestoreCredential 類型,其中包含公開金鑰。

處理登入回應

將公開金鑰從應用程式傳送至依賴方伺服器,以便用於登入使用者。在伺服器端,這項動作與使用密碼金鑰登入類似。在伺服器上處理密碼金鑰登入作業的程式碼,也可以處理還原金鑰登入作業。如要進一步瞭解密碼金鑰的伺服器端實作,請參閱「使用密碼金鑰登入」。

刪除還原金鑰

Credential Manager 是無狀態,且不會偵測使用者活動,因此不會在使用後自動刪除還原金鑰。如要刪除還原金鑰,請呼叫 clearCredentialState 方法。為安全起見,請在使用者登出時刪除金鑰。這樣一來,使用者下次在同一部裝置上開啟應用程式時,就會登出並收到重新登入的提示。

解除安裝應用程式會解讀為從該裝置刪除對應還原金鑰的意圖,類似於使用者登出時的意圖。

只有在下列情況下,系統才會移除還原金鑰:

  • 系統層級動作:使用者解除安裝應用程式或清除其資料。
  • 應用程式層級呼叫:在應用程式程式碼中處理使用者登出時,呼叫 clearCredentialState(),以程式輔助方式刪除金鑰。

當使用者登出應用程式時,請呼叫 CredentialManager 物件的 clearCredentialState() 方法。

// 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)