身為 Android 開發人員,您不斷尋找提升安全性、改善使用者體驗及簡化開發作業的方法。Zoho 是一套以安全性和流暢體驗為主的雲端軟體,在 OneAuth Android 應用程式中採用密碼金鑰後,成效大幅提升。
自 2024 年整合密碼金鑰後,Zoho 的登入速度比先前的方法快 6 倍,且密碼金鑰採用率逐月成長 31% 。
本個案研究探討 Zoho 如何採用密碼金鑰和 Android 的 Credential Manager API,解決驗證困難的問題。這份報告詳細說明技術導入程序,並重點介紹成效顯著的結果。
克服驗證問題
Zoho 採用多種驗證方法來保護使用者帳戶。包括 Zoho OneAuth,這是他們自己的多重驗證 (MFA) 解決方案,支援以密碼為基礎的驗證,以及使用推播通知、QR code 和限時動態密碼 (TOTP) 的無密碼驗證。Zoho 也支援同盟登入,可透過安全宣告標記語言 (SAML) 和其他第三方身分識別提供者進行驗證。
挑戰
與許多機構一樣,Zoho 的目標是提升驗證安全性與使用者體驗,同時減輕營運負擔。促使我們採用密碼金鑰的主要挑戰包括:
- 安全漏洞:傳統的密碼驗證方法容易遭到網路釣魚攻擊,也可能導致密碼外洩。
- 使用者操作障礙:密碼疲乏導致使用者忘記密碼、感到沮喪,並更加依賴繁瑣的救援程序。
- 作業效率不彰:處理密碼重設和多重驗證問題會產生大量支援費用。
- 擴充性問題:使用者人數不斷增加,因此需要更安全有效率的驗證解決方案。
為什麼要改用密碼金鑰?
Zoho 應用程式導入密碼金鑰,採用無密碼方式解決驗證問題,大幅提升安全性及使用者體驗。這項解決方案採用防網路釣魚驗證機制、雲端同步處理的憑證,方便使用者跨裝置存取,並提供生物特徵辨識 (例如指紋或臉部辨識)、PIN 碼或解鎖圖案等安全登入方式,減少傳統密碼相關的安全性漏洞和不便。
Zoho 採用 Credential Manager 支援密碼金鑰後,登入時間最多縮短 6 倍,與密碼相關的支援費用也大幅減少,使用者採用率相當高。密碼金鑰登入次數在 4 個月內增加一倍,每月成長率達 31% 。Zoho 使用者現在可以更快速輕鬆地登入,並享有防範網路釣魚的安全保障。
在 Android 上使用 Credential Manager 實作
那麼,Zoho 是如何達成這些成果的呢?他們使用 Android 的 Credential Manager API,這是建議在 Android 上實作驗證的 Jetpack 程式庫。
Credential Manager 提供整合式 API,可簡化各種驗證方法的處理程序。不必再為密碼、密碼金鑰和聯合登入 (例如使用 Google 帳戶登入) 處理不同的 API,只要使用單一介面即可。
在 Zoho 導入密碼金鑰時,需要調整用戶端和伺服器端。以下詳細說明密碼金鑰的建立、登入和伺服器端導入程序。
建立密碼金鑰
如要建立密碼金鑰,應用程式會先從 Zoho 的伺服器擷取設定詳細資料。這個程序包括指紋或臉部辨識等獨特的驗證方式。應用程式會使用這項驗證資料 (格式為 requestJson 字串) 建構 CreatePublicKeyCredentialRequest。接著,應用程式會呼叫 credentialManager.createCredential 方法,提示使用者透過裝置螢幕鎖定 (生物特徵辨識、指紋、PIN 碼等) 進行驗證。
使用者確認後,應用程式會收到新的密碼金鑰憑證資料,並傳回 Zoho 的伺服器進行驗證,伺服器接著會儲存與使用者帳戶連結的密碼金鑰資訊。應用程式會擷取並處理程序期間發生的失敗或使用者取消情況。
登入
Zoho Android 應用程式會向 Zoho 的後端伺服器要求登入選項 (包括專屬的 challenge),藉此啟動密碼金鑰登入程序。應用程式接著會使用這項資料建構 GetCredentialRequest,指出將使用密碼金鑰進行驗證。然後使用這項要求叫用 Android CredentialManager.getCredential() API。這項操作會觸發標準化的 Android 系統介面,提示使用者選擇 Zoho 帳戶 (如果有多個密碼金鑰),並使用裝置設定的螢幕鎖定 (指紋、臉部掃描或 PIN 碼) 進行驗證。驗證成功後,Credential Manager 會將已簽署的聲明 (登入證明) 傳回給 Zoho 應用程式。應用程式會將這項聲明轉送至 Zoho 的伺服器,伺服器會根據使用者儲存的公開金鑰驗證簽章,並驗證挑戰,完成安全登入程序。
伺服器端導入
Zoho 的後端系統已符合 FIDO WebAuthn 規範,因此在改用密碼金鑰時,伺服器端實作程序相當順暢。不過,您仍須進行特定修改,才能完全整合密碼金鑰功能。
最重大的挑戰是調整憑證儲存空間。Zoho 現有的驗證方法主要使用密碼和 FIDO 安全金鑰進行多重驗證,與密碼金鑰 (以加密公開金鑰為基礎) 相比,需要不同的儲存方式。為解決這個問題,Zoho 導入了新的資料庫結構定義,專門用於根據 WebAuthn 協定安全地儲存密碼金鑰公開金鑰和相關資料。這個新系統是與查詢機制一併建構,可根據使用者和裝置資訊驗證及擷取憑證,確保與舊版驗證方法回溯相容。
另一項伺服器端調整作業,是導入處理 Android 裝置要求的機制。Android 應用程式發出的密碼金鑰要求會使用獨特的來源格式 (android:apk-key-hash:example),與使用 URI 格式 (https://example.com/app) 的標準網路來源不同。因此,伺服器邏輯必須更新,才能正確剖析這個格式、擷取應用程式簽署憑證的 SHA-256 指紋雜湊,並根據預先註冊的清單驗證。這個驗證步驟可確保驗證要求確實來自 Zoho 的 Android 應用程式,並防範網路釣魚攻擊。
下列程式碼片段說明伺服器如何檢查 Android 專屬來源格式,並驗證憑證雜湊:
val origin: String = clientData.getString("origin") if (origin.startsWith("android:apk-key-hash:")) { val originSplit: List<String> = origin.split(":") if (originSplit.size > 3) { val androidOriginHashDecoded: ByteArray = Base64.getDecoder().decode(originSplit[3]) if (!androidOriginHashDecoded.contentEquals(oneAuthSha256FingerPrint)) { throw IAMException(IAMErrorCode.WEBAUTH003) } } else { // Optional: Handle the case where the origin string is malformed } }
處理錯誤
Zoho 導入完善的錯誤處理機制,可管理使用者和開發人員遇到的錯誤。使用者手動取消密碼金鑰設定時,系統會顯示常見錯誤 CreateCredentialCancellationException。Zoho 追蹤這項錯誤的頻率,以評估可行的使用者體驗改善措施。根據 Android 的 UX 建議,Zoho 採取了相關措施,讓使用者更瞭解密碼金鑰、確保使用者知道密碼金鑰的可用性,並在後續登入嘗試中推廣密碼金鑰。
以下程式碼範例說明 Zoho 如何處理最常見的密碼金鑰建立錯誤:
private fun handleFailure(e: CreateCredentialException) {
val msg = when (e) {
is CreateCredentialCancellationException -> {
Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_CANCELLED", GROUP_NAME)
Analytics.addNonFatalException(e)
"The operation was canceled by the user."
}
is CreateCredentialInterruptedException -> {
Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_INTERRUPTED", GROUP_NAME)
Analytics.addNonFatalException(e)
"Passkey setup was interrupted. Please try again."
}
is CreateCredentialProviderConfigurationException -> {
Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_PROVIDER_MISCONFIGURED", GROUP_NAME)
Analytics.addNonFatalException(e)
"Credential provider misconfigured. Contact support."
}
is CreateCredentialUnknownException -> {
Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_UNKNOWN_ERROR", GROUP_NAME)
Analytics.addNonFatalException(e)
"An unknown error occurred during Passkey setup."
}
is CreatePublicKeyCredentialDomException -> {
Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_WEB_AUTHN_ERROR", GROUP_NAME)
Analytics.addNonFatalException(e)
"Passkey creation failed: ${e.domError}"
}
else -> {
Analytics.addAnalyticsEvent(eventProtocol: "PASSKEY_SETUP_FAILED", GROUP_NAME)
Analytics.addNonFatalException(e)
"An unexpected error occurred. Please try again."
}
}
}在內部網路環境中測試密碼金鑰
Zoho 最初在封閉的內部網路環境中測試密碼金鑰時,面臨了挑戰。Google 密碼管理工具的驗證程序需要公開網域存取權,才能驗證憑證方 (RP) 網域。不過,Zoho 的內部測試環境缺少這項公用網際網路存取權,導致驗證程序失敗,無法順利測試密碼金鑰驗證。為解決這個問題,Zoho 建立了可公開存取的測試環境,包括代管含有資產連結檔案和網域驗證的臨時伺服器。
這個範例來自 Zoho 公開測試環境中使用的 assetlinks.json 檔案,示範如何將憑證方網域與指定的 Android 應用程式建立關聯,以進行密碼金鑰驗證。
[
{
"relation": [
"delegate_permission/common.handle_all_urls",
"delegate_permission/common.get_login_creds"
],
"target": {
"namespace": "android_app",
"package_name": "com.zoho.accounts.oneauth",
"sha256_cert_fingerprints": [
"SHA_HEX_VALUE"
]
}
}
]與現有 FIDO 伺服器整合
Android 的密碼金鑰系統採用最新的 FIDO2 WebAuthn 標準。這項標準要求採用特定 JSON 格式的要求,有助於維持原生應用程式和網路平台之間的一致性。為啟用 Android 密碼金鑰支援功能,Zoho 進行了小幅度的相容性和結構變更,以正確產生及處理符合必要 FIDO2 JSON 結構的要求。
本次伺服器更新包含幾項具體的技術調整:
1. 轉換編碼:伺服器會先將 Base64 網址編碼 (WebAuthn 常用的憑證 ID 等欄位) 轉換為標準 Base64 編碼,再儲存相關資料。下列程式碼片段說明如何將 rawId 編碼為標準 Base64:
// Convert rawId bytes to a standard Base64 encoded string for storage val base64RawId: String = Base64.getEncoder().encodeToString(rawId.toByteArray())
2. 傳輸機制清單格式:為確保資料處理作業一致,伺服器邏輯會將傳輸機制清單 (例如 USB、NFC 和藍牙,這些機制會指定驗證器通訊方式) 視為 JSON 陣列處理。
3. 用戶端資料對齊:Zoho 團隊調整了伺服器編碼和解碼 clientDataJson 欄位的方式。確保資料結構完全符合 Zoho 現有內部 API 的預期。下例說明伺服器處理用戶端資料前,套用至資料的部分轉換邏輯:
private fun convertForServer(type: String): String { val clientDataBytes = BaseEncoding.base64().decode(type) val clientDataJson = JSONObject(String(clientDataBytes, StandardCharsets.UTF_8)) val clientJson = JSONObject() val challengeFromJson = clientDataJson.getString("challenge") // 'challenge' is a technical identifier/token, not localizable text. clientJson.put("challenge", BaseEncoding.base64Url() .encode(challengeFromJson.toByteArray(StandardCharsets.UTF_8))) clientJson.put("origin", clientDataJson.getString("origin")) clientJson.put("type", clientDataJson.getString("type")) clientJson.put("androidPackageName", clientDataJson.getString("androidPackageName")) return BaseEncoding.base64().encode(clientJson.toString().toByteArray()) }
使用者指引和驗證偏好設定
Zoho 密碼金鑰策略的中心目標是鼓勵使用者採用密碼金鑰,同時提供彈性,以符合不同機構的需求。我們透過審慎的使用者介面設計和政策控管,達成了這項目標。
Zoho 瞭解各機構的安全需求不同,為此,Zoho 實作了以下措施:
- 管理員強制執行:管理員可以透過 Zoho Directory 管理面板,將密碼金鑰指定為整個機構的強制預設驗證方法。啟用這項政策後,員工下次登入時必須設定密碼金鑰,並在日後使用密碼金鑰登入。
- 使用者選擇:如果機構未強制執行特定政策,使用者可自行控管。登入時,使用者可以選擇偏好的驗證方式,透過驗證設定選取密碼金鑰或其他設定選項。
為讓使用者輕鬆採用密碼金鑰,Zoho 實作了下列功能:
- 設定簡單:Zoho OneAuth 行動應用程式 (適用於 Android 和 iOS) 直接整合了密碼金鑰設定。使用者隨時可以在應用程式中輕鬆設定密碼金鑰,順利完成轉換。
- 一致的存取體驗:我們在主要使用者接觸點導入密碼金鑰支援功能,確保使用者可以透過下列方式註冊及驗證密碼金鑰:
- Zoho OneAuth 行動應用程式 (Android 和 iOS);
- Zoho 網頁的「帳戶」頁面。
無論是管理員強制執行或使用者自行選擇,這個方法都能確保設定及使用密碼金鑰的程序簡單易懂,並整合到使用者已在使用的平台。如要進一步瞭解如何為密碼金鑰驗證程序建立流暢的使用者流程,請參閱我們詳盡的密碼金鑰使用者體驗指南。
對開發速度和整合效率的影響
相較於舊版登入流程,Credential Manager 這項整合式 API 也提升了開發人員的工作效率。這項功能簡化了分別處理多種驗證方法和 API 的複雜度,因此整合速度更快 (從數月縮短為數週),實作錯誤也減少了。這項措施簡化了登入程序,並提升整體穩定性。
Zoho 透過 Credential Manager 實作密碼金鑰,在各方面都獲得顯著且可衡量的成效:
- 大幅提升速度
- 與傳統密碼驗證相比,登入速度快上 2 倍。
- 與使用電子郵件或簡訊動態密碼驗證的使用者名稱或手機號碼相比,登入速度快 4 倍。
- 與使用者名稱、密碼和簡訊或 Authenticator 動態密碼驗證相比,登入速度快 6 倍。
- 降低支援成本
- 減少密碼相關支援要求,尤其是忘記密碼的情況。
- 降低成本:現有使用者可直接使用密碼金鑰登入,因此採用簡訊驗證的雙重驗證機制可降低成本。
- 使用者採用率高且安全性提升:
- 密碼金鑰登入次數在短短 4 個月內增加一倍,顯示使用者接受度很高。
- 改用密碼金鑰後,使用者完全不必擔心常見的網路釣魚和密碼外洩威脅。
- 這項計畫的採用率每月成長 31%,每天都有更多使用者受惠,防範網路釣魚和 SIM 卡交換等安全漏洞。
建議做法與最佳做法
如要在 Android 上成功實作密碼金鑰,開發人員應考慮下列最佳做法:
- 運用 Android 的 Credential Manager API:
- Credential Manager 可簡化憑證擷取作業、減少開發人員的工作量,並確保驗證體驗一致。
- 在單一介面中處理密碼、密碼金鑰和聯合登入流程。
- 從其他 FIDO 驗證解決方案遷移時,請確保資料編碼一致:
- 從其他 FIDO 驗證解決方案 (例如 FIDO 安全金鑰) 遷移時,請務必處理所有輸入/輸出內容的格式一致性。
- 最佳化錯誤處理和記錄:
- 導入完善的錯誤處理機制,提供流暢的使用者體驗。
- 提供本地化錯誤訊息,並使用詳細記錄來偵錯及解決非預期的失敗問題。
- 向使用者說明密碼金鑰救援選項:
- 主動引導使用者瞭解救援選項,避免發生帳戶遭鎖定的情況。
- 監控採用率指標和使用者意見回饋:
- 追蹤使用者參與度、密碼金鑰採用率和登入成功率,持續提升使用者體驗。
- 對不同的驗證流程執行 A/B 測試,以提高轉換率和留客率。
密碼金鑰搭配 Android Credential Manager API,可提供強大的整合式驗證解決方案,提升安全性並簡化使用者體驗。密碼金鑰可大幅降低網路釣魚、憑證遭竊和未經授權存取的風險。我們鼓勵開發人員在應用程式中試用這項功能,為使用者提供最安全的驗證方式。
開始使用密碼金鑰和 Credential Manager
使用公開程式碼範例,在 Android 裝置上實際操作密碼金鑰和 Credential Manager。
如有任何問題,歡迎透過 Android 憑證問題追蹤器與我們聯絡。
繼續閱讀
-
個案研究
Uber 運用 Android 憑證還原 API 簡化新裝置登入程序,預計每年可減少 400 萬次手動登入,並提高使用者留存率。
Niharika Arora • 5 分鐘可讀完
-
個案研究
X 是一款社群媒體應用程式,提供即時評論,協助全球近 5 億名使用者掌握新聞、娛樂、體育和政治等各類事件的完整脈絡。
Niharika Arora • 3 分鐘可讀完
-
個案研究
Monzo 是英國數位銀行,目前有 1,500 萬名客戶,且人數持續增加中。隨著應用程式規模擴大,工程團隊發現應用程式啟動時間是需要改善的關鍵領域,但擔心這會需要大幅變更程式碼集。
Ben Weiss • 閱讀時間:2 分鐘
隨時掌握最新消息
每週透過電子郵件接收最新的 Android 開發洞察資訊。