静默登录
====

#### 场景介绍

在应用卸载重装、用户换机等场景，如登录的华为账号与应用重装、换机前一致，应用可通过Account Kit提供的静默登录方式即不需要用户点击登录/注册按钮，即可获取用户的身份标识UnionID/OpenID，完成用户的静默登录。

#### 约束与限制

静默登录能力支持Phone、Tablet、PC/2in1设备。并且从5.1.0(18)版本开始，新增支持Wearable设备；从5.1.1(19)版本开始，新增支持TV设备；从26.0.0版本开始，新增支持Car设备。

#### 业务流程

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/72/v3/RL3Rxk9ZTje0Sk4CHp8MaA/zh-cn_image_0000002625108557.png?HW-CC-KV=V1&HW-CC-Date=20260612T073547Z&HW-CC-Expire=86400&HW-CC-Sign=CB4122373990CD87C04E9E1C662D2DB0E1516AAF8349BCCE53403F711DD2EA85)

流程说明：

1.  调用登录API阶段（序号1-3）：
    
    1.  用户使用华为账号登录过应用，应用卸载重装、用户换机后再进入应用时，应用传forceLogin = false等参数调用登录API。
    2.  如华为账号已登录，且API调用成功，应用能获取到Authorization Code等登录结果。注意：如华为账号未登录，应用会获取到[1001502001 用户未登录华为账号](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/errorcode-account-kit#section1001502001-用户未登录华为账号)错误码，再根据需要自行处理。
2.  用户关联应用账号阶段（序号4-13）：
    
    1.  应用服务端通过Authorization Code获取到Access Token，再使用Access Token调用[解析凭证接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-get-token-info#接口原型)获取用户相关信息。通过Authorization Code凭证获取用户信息可以有效避免黑客通过数据遍历、身份伪造、重放攻击等手段导致的安全风险。
    2.  应用服务端将业务登录凭证SessionId、UnionID/OpenID传给应用，应用获取到UnionID/OpenID可用于判断华为账号是否登录等功能。
    3.  应用对用户身份标识UnionID/OpenID、业务登录凭证SessionId信息进行安全认证后完成静默登录。

#### 接口说明

静默登录关键接口如下表所示，具体API说明详见[API参考](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication)。

| 接口名 | 描述 |
| :-- | :-- |
| [createLoginWithHuaweiIDRequest](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#createloginwithhuaweiidrequest)(): [LoginWithHuaweiIDRequest](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#loginwithhuaweiidrequest) | 创建账号登录请求。[LoginWithHuaweiIDRequest](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#loginwithhuaweiidrequest)中的forceLogin参数用来控制当用户未登录华为账号时，是否强制拉起华为账号登录界面，静默登录场景设置为false。 |
| [constructor](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#constructor)(context?: [common.Context](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-app-ability-common#context)) | 创建登录请求Controller。 |
| [executeRequest](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#executerequest-1)(request: [AuthenticationRequest](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#authenticationrequest)): Promise<[AuthenticationResponse](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#authenticationresponse)\> | 通过Promise方式执行登录操作。 |

#### 开发前提

在进行代码开发前，请确保已按照“开发准备”章节中的指导完成[配置签名和指纹](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/account-sign-fingerprints)、[配置Client ID](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/account-client-id)。此场景无需申请账号权限。

#### 客户端开发

1.  导入[authentication](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication)模块及相关公共模块。
    
    import { authentication } from '@kit.AccountKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { util } from '@kit.ArkTS';
    import { BusinessError } from '@kit.BasicServicesKit';
    
2.  创建登录请求并设置参数。
    
    // 创建登录请求，并设置参数
    const loginRequest = new authentication.HuaweiIDProvider().createLoginWithHuaweiIDRequest();
    // false表示静默登录
    loginRequest.forceLogin = false;
    // 建议使用generateRandomUUID生成state，可用于一致性比对，防止跨站攻击
    loginRequest.state = util.generateRandomUUID();
    
3.  调用[AuthenticationController](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#authenticationcontroller)对象的[executeRequest](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-authentication#executerequest-1)方法执行登录请求，并处理登录结果，获取到Authorization Code及ID Token。之后将Authorization Code传给应用服务端处理，可参考[客户端与服务端交互开发](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/account-phone-unionid-login#客户端与服务端交互开发)的开发步骤a和b。应用可以通过公开的网址获取到华为账号服务器发布的公钥，对签名和ID Token中的必要信息进行验证，以证明其没有被篡改过。解析ID Token可参考[ID Token解析与验证](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/account-faq-12#解析与验证)。
    
    // 执行登录请求
    try {
      const controller = new authentication.AuthenticationController();
      controller.executeRequest(loginRequest).then((response: authentication.LoginWithHuaweiIDResponse) => {
        const loginWithHuaweiIDResponse = response as authentication.LoginWithHuaweiIDResponse;
        const state = loginWithHuaweiIDResponse.state;
        if (state && loginRequest.state !== state) {
          hilog.error(0x0000, 'testTag', \`Failed to login. The state is different, response state: ${state}\`);
          return;
        }
        hilog.info(0x0000, 'testTag', 'Succeeded in logging in.');
        const loginWithHuaweiIDCredential = loginWithHuaweiIDResponse?.data;
        const authorizationCode = loginWithHuaweiIDCredential?.authorizationCode;
        // 开发者处理authorizationCode
      }).catch((error: BusinessError) => {
        dealAllError(error);
      });
    } catch (error) {
      dealAllError(error);
    }
    
    // 错误处理
    function dealAllError(error: BusinessError): void {
      hilog.error(0x0000, 'testTag', \`Failed to login. Code: ${error.code}, message: ${error.message}\`);
      // 在应用登录涉及UI交互场景下，建议按照如下错误码指导提示用户
      if (error.code === ErrorCode.ERROR\_CODE\_LOGIN\_OUT) {
        // 用户未登录华为账号，请登录华为账号并重试或者尝试使用其他方式登录
      } else if (error.code === ErrorCode.ERROR\_CODE\_NETWORK\_ERROR) {
        // 网络错误，请检查当前网络状态并重试
      } else if (error.code === ErrorCode.ERROR\_CODE\_INTERNAL\_ERROR) {
        // 登录失败，请尝试使用其他方式登录
      } else if (error.code === ErrorCode.ERROR\_CODE\_USER\_CANCEL) {
        // 用户取消授权
      } else if (error.code === ErrorCode.ERROR\_CODE\_SYSTEM\_SERVICE) {
        // 系统服务异常，请稍后重试或者尝试使用其他方式登录
      } else if (error.code === ErrorCode.ERROR\_CODE\_REQUEST\_REFUSE) {
        // 重复请求，应用无需处理
      } else {
        // 应用登录失败，请尝试使用其他方式登录
      }
    }
    
    export enum ErrorCode {
      // 账号未登录
      ERROR\_CODE\_LOGIN\_OUT = 1001502001,
      // 网络错误
      ERROR\_CODE\_NETWORK\_ERROR = 1001502005,
      // 内部错误
      ERROR\_CODE\_INTERNAL\_ERROR = 1001502009,
      // 用户取消授权
      ERROR\_CODE\_USER\_CANCEL = 1001502012,
      // 系统服务异常
      ERROR\_CODE\_SYSTEM\_SERVICE = 12300001,
      // 重复请求
      ERROR\_CODE\_REQUEST\_REFUSE = 1001500002
    }
    

#### 服务端开发

1.  应用服务端使用Client ID、Client Secret、Authorization Code调用[获取用户级凭证接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-obtain-user-token#接口原型)向华为账号服务器请求获取Access Token、Refresh Token。
    
2.  使用Access Token调用[解析凭证接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-get-token-info#接口原型)获取用户的UnionID。
    
    **Access Token过期处理**
    
    由于Access Token的有效期仅为60分钟，当Access Token失效或者即将失效时（可通过[REST API错误码](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-get-token-info#错误码)判断），可以使用Refresh Token（有效期180天）通过[刷新用户级凭证接口](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-obtain-refresh-token#接口原型)向华为账号服务器请求获取新的Access Token。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/9b/v3/j9TOMPK3SIiHHdDeFyPCiw/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073547Z&HW-CC-Expire=86400&HW-CC-Sign=5257803ACA0462BD8CC5FDEC50F6E5757D119804924C561E0E95D38D8ECFDDD3)
    
    1.  当Access Token失效时，若应用不使用Refresh Token向华为账号服务器请求获取新的Access Token，账号的授权信息将会失效，导致使用Access Token的功能都会失败。
        
    2.  当Access Token非正常失效（如修改密码、退出账号、删除设备）时，应用可重新登录授权获取Authorization Code，向华为账号服务器请求获取新的Access Token。
        
    
    **Refresh Token过期处理**
    
    由于Refresh Token的有效期为180天，当Refresh Token失效后（可通过[REST API错误码](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/account-api-obtain-refresh-token#错误码)判断），应用服务端需要通知客户端，重新调用授权接口，请求用户重新授权。
    
3.  应用在自己的用户体系通过查询获取的UnionID判断该用户是否已关联。如已关联，则完成用户登录；如未关联，则创建新用户，绑定UnionID，完成用户登录。