當前數字時代,人們日常頻繁使用的密碼,成了"記憶負擔",密碼太短不安全,密碼太長又記不住,如果忘記密碼,找回流程也較繁瑣,嚴重影響了用户在應用登錄或支付場景中的使用體驗。

基於此,HarmonyOS SDK在線認證服務(Online Authentication Kit)遵循FIDO(Fast Identity Online)、FIDO2、IIFAA(互聯網可信認證聯盟)和SOTER標準免密認證規範,提供了免密身份認證的移動端能力,並基於FIDO2標準協議構建了產品化的通行密鑰能力,借用通行密鑰,用户可使用指紋、人臉或手機解鎖PIN碼登錄應用,實現一種簡單又安全的登錄方式。

場景介紹

通行密鑰服務主要提供了通行密鑰註冊、本地免密認證和跨設備掃碼認證的能力,具體應用場景如下:

● 註冊通行密鑰

在需要給本地應用或網頁提供一種方便、快速、安全的登錄方式時,應用可以使用通行密鑰服務的通行密鑰註冊能力為用户創建通行密鑰。

互聯網三大巨頭宣佈將支持FIDO無密碼登錄,虹膜識別被納入其中_錯誤碼

● 使用通行密鑰登錄本設備的應用或網頁賬號

用户在登錄本設備的應用或者網頁賬號時,需要驗證用户的身份,可以使用通行密鑰服務的本地免密認證能力,實現快速登錄。

互聯網三大巨頭宣佈將支持FIDO無密碼登錄,虹膜識別被納入其中_服務器_02

● 使用通行密鑰跨設備掃碼登錄其他設備的應用或網頁賬號

用户在其他設備上登錄應用或網頁時,需要驗證用户的身份,可以使用通行密鑰服務的跨設備掃碼認證能力。

互聯網三大巨頭宣佈將支持FIDO無密碼登錄,虹膜識別被納入其中_服務器_03

約束與限制

應用需滿足以下條件,才能使用該功能。

  • 開發者的業務需要接入符合FIDO2標準的協議,並部署符合FIDO2標準協議的FIDO服務端。
  • 移動端設備需要支持生物特徵(指紋或3D人臉),且當前移動端設備支持ATL4級別的認證可信等級。
  • 通行密鑰服務需要聯網以及藍牙能力,以便提供完整的在線身份校驗服務。應用在調用本服務API前,需將通行密鑰服務聯網、使用藍牙行為向用户明示,並且取得用户同意。
  • 通行密鑰服務需要將三方應用中的用户暱稱及標識符信息上傳至網絡中繼服務器,用於跨設備掃碼認證場景,以便實現兩台設備的認證數據通信。應用在調用本服務API前,需將收集的個人數據信息向用户明示,並且取得用户同意。

開發步驟

通行密鑰服務提供基於FIDO2標準協議的FIDO客户端實現,這裏僅演示FIDO客户端相關API的使用,涉及應用服務器及FIDO服務器的相關處理由開發者自行實現,請參考FIDO2標準協議。

  1. 需要業務方自行根據FIDO2標準協議部署FIDO服務器。
  2. 導入相關模塊。
1. import { BusinessError } from '@kit.BasicServicesKit';

import { UIContext } from '@kit.ArkUI'

import { common } from '@kit.AbilityKit';

import { fido2 } from '@kit.OnlineAuthenticationKit';
  1. 註冊通行密鑰。

在註冊通行密鑰階段,先要獲取能力信息。調用getClientCapabilities接口獲取認證能力列表,並且調用getPlatformAuthenticators接口獲取平台認證器能力信息。

uiContext1: UIContext = this.getUIContext();
uiContext: common.UIAbilityContext = this.uiContext1.getHostContext() as common.UIAbilityContext; // 使用uiContext需要獲取頁面UIAbility的Context,一個頁面獲取一次即可

try {
  // 獲取認證能力列表
  let clientCapabilities: Map<fido2.ClientCapability, boolean> = await fido2.getClientCapabilities(this.uiContext);
  console.info("Succeeded in doing getClientCapabilities.");
} catch (error) {
  let message = (error as BusinessError).message;
  let code = (error as BusinessError).code;
  console.error(`Failed to call getClientCapabilities error code is ${code}, message is ${message}`);
  // 業務根據錯誤碼判斷異常類型,進行相應處理,詳見錯誤碼參考
}

try {
  // 獲取平台認證器能力
  let platformAuthenticators: Array<fido2.AuthenticatorMetadata> =
    await fido2.getPlatformAuthenticators(this.uiContext);
  console.info("Succeeded in doing getPlatformAuthenticators.");
} catch (error) {
  let message = (error as BusinessError).message;
  let code = (error as BusinessError).code;
  console.error(`Failed to call getPlatformAuthenticators error code is ${code}, message is ${message}`);
  // 業務根據錯誤碼判斷異常類型,進行相應處理,詳見錯誤碼參考
}

接着,訪問FIDO服務器,獲取註冊報文,就可以調用register接口進行通行密鑰註冊了。

// pkOptions為應用從FIDO服務端獲取的註冊報文, credentialCreationOp為應用組裝註冊信息
let credentialCreationOp: fido2.CredentialCreationOptions = {
  publicKey: pkOptions
};

try {
  // 調用register進行通行密鑰註冊
  let publicKeyAttestationCredential: fido2.PublicKeyAttestationCredential =
    await fido2.register(this.uiContext, credentialCreationOp);
} catch (error) {
  let message = (error as BusinessError).message;
  let code = (error as BusinessError).code;
  console.error(`Failed to call register error code is ${code}, message is ${message}`);
  // 業務根據錯誤碼判斷異常類型,進行相應處理,詳見錯誤碼參考
}

最後,應用使用註冊結果(publicKeyAttestationCredential)組裝註冊響應報文,發送至FIDO服務端進行驗證,獲取註冊結果報文。

  1. 使用通行密鑰進行身份認證。

在使用通行密鑰進行身份認證階段,先要獲取能力信息,調用getClientCapabilities接口獲取認證能力列表,並且調用getPlatformAuthenticators接口獲取平台認證器能力信息。

// 使用uiContext需要獲取頁面UIAbility的Context,一個頁面獲取一次即可
let uiContext: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;

try {
  // 獲取認證能力列表
  let clientCapabilities: Map<fido2.ClientCapability, boolean> = await fido2.getClientCapabilities(this.uiContext);
  console.info("Succeeded in doing getClientCapabilities.");
} catch (error) {
  let message = (error as BusinessError).message;
  let code = (error as BusinessError).code;
  console.error(`Failed to call getClientCapabilities error code is ${code}, message is ${message}`);
  // 業務根據錯誤碼判斷異常類型,進行相應處理,詳見錯誤碼參考
}

try {
  // 獲取平台認證器能力
  let platformAuthenticators: Array<fido2.AuthenticatorMetadata> =
    await fido2.getPlatformAuthenticators(this.uiContext);
  console.info("Succeeded in doing getPlatformAuthenticators.");
} catch (error) {
  let message = (error as BusinessError).message;
  let code = (error as BusinessError).code;
  console.error(`Failed to call getPlatformAuthenticators error code is ${code}, message is ${message}`);
  // 業務根據錯誤碼判斷異常類型,進行相應處理,詳見錯誤碼參考
}

接着,通過訪問FIDO服務器,獲取認證報文,並調用authenticate接口進行認證。

// authPub為應用從FIDO服務端獲取的認證報文,authCredentialRequestOptions為應用組裝的認證信息
let authCredentialRequestOptions: fido2.CredentialRequestOptions = {
  publicKey: authPub,
  mediation: "optional" as fido2.CredentialMediationRequirement
}

try {
  // 調用authenticate接口進行認證
  let pkAssertionCredential: fido2.PublicKeyAssertionCredential =
    await fido2.authenticate(this.uiContext, authCredentialRequestOptions);
} catch (error) {
  let message = (error as BusinessError).message;
  let code = (error as BusinessError).code;
  console.error(`Failed to call authenticateerror code is ${code}, message is ${message}`);
  // 業務根據錯誤碼判斷異常類型,進行相應處理,詳見錯誤碼參考
}

最後,應用使用認證結果(pkAssertionCredential)組裝認證響應報文,發送至FIDO服務端進行驗證,獲取認證結果報文。