1e41f4b71Sopenharmony_ci# User Authentication 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Function 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciUser authentication is indispensable in identity authentication scenarios, such as device unlocking, payment, and app logins. The user authentication framework (User_auth) manages the mappings between user identities and authentication credential templates in a unified manner. It schedules executors implemented by basic authentication services (including PIN authentication and facial recognition) to register user authentication credentials, delete credentials, obtain related information, and complete authentication. The figure below shows the architecture of user authentication. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciThe User_auth driver is developed based on the Hardware Driver Foundation (HDF). It shields hardware differences and provides stable user authentication capabilities for apps and account management system ability (SA). It supports user credential management, authentication information enrollment, authentication scheme generation, and executor information management. 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci**Figure 1** User authentication architecture 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci### Basic Concepts 16e41f4b71Sopenharmony_ciThe identity authentication consists of the User_auth framework and basic authentication services (including PIN authentication and facial recognition). It supports basic functions such as setting and deleting user credentials and performing authentication. 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ci- Authentication credential information 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ci An authentication credential template is generated when a user sets a password or enrolls facial information. The credential information consists of the user identity information and credential template information. The authentication is successful when the credential data generated matches the credential template information. 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci- Authentication credential template 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci The authentication credential template is generated and stored by the authentication service when a user sets the authentication credential. Each template has an ID to index a set of template information files. The template information needs to be compared with the authentication data generated during authentication to complete identity authentication. 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci- Executor 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci The executor collects, processes, stores, and compares data for authentication. Each authentication service provides the executor capabilities, which are scheduled by User_auth to implement basic capabilities. 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ci- Executor role 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci - Executor: independently completes the entire process of credential registration and identity authentication. The executor can collect, process, store, and compare data to complete the authentication. 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci - Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication. 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ci - Authenticator: processes data, obtains the stored credential template, and compares it with the authentication information generated. 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ci- Executor type 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci The authentication algorithm varies depending on the authentication mode and device used. Different executor types are defined based on the supported algorithm type or the device in use. 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci- Executor security level 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci Security level of the runtime environment when an executor provides capabilities. 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci- User_auth public key & executor public key 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ci To ensure user data security and authentication result accuracy, measures must be taken to protect the integrity of the key information exchanged between User_auth and basic authentication services. Public keys must be exchanged when the executor provided by a basic authentication service interworks with User_auth. 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ci - The executor uses the User_auth public key to verify scheduling instructions. For example, if a face image template is locked, the related facial authentication capability cannot be used. The instruction for unlocking the face image template must be verified before being executed. 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ci - User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ci 55e41f4b71Sopenharmony_ci- Authentication result trust level 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci The trust level of the authentication result varies, depending on the authentication mode and the security level of the authentication execution environment. 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci- Authentication scheme 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci An authentication scheme contains information about the authentication mode, trust level of the authentication result, executor, and credential. 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci- Scheduling information 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci Scheduling information includes the executor information and credential template information required by the executor to process requests. User_auth schedules the executor to implement basic authentication capabilities. 66e41f4b71Sopenharmony_ci 67e41f4b71Sopenharmony_ci- SA 68e41f4b71Sopenharmony_ci 69e41f4b71Sopenharmony_ci SAs are loaded by the System Ability Manager to provide basic system capabilities for OpenHarmony devices. 70e41f4b71Sopenharmony_ci 71e41f4b71Sopenharmony_ci- Kit 72e41f4b71Sopenharmony_ci 73e41f4b71Sopenharmony_ci The kit provides basic APIs for third-party applications. 74e41f4b71Sopenharmony_ci 75e41f4b71Sopenharmony_ci- Inner API 76e41f4b71Sopenharmony_ci 77e41f4b71Sopenharmony_ci Inner API is an API provided by OpenHarmony for system applications. 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ci- IDL interface 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci An Interface Definition Language (IDL) is a language that lets a program or object written in one language communicate with another program written in an unknown language. An IDL compiler generates client stub files and server framework files. This document describes how to use the client and server generated by the IDL interface to implement communication between the User_auth service and driver. For details, see [IDL](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md). 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci- IPC 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci Inter-Process Communication (IPC) is a mechanism that allows processes to communicate with each other. For details, see [IPC](https://gitee.com/openharmony/communication_ipc/blob/master/README.md). 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ci- HDI 88e41f4b71Sopenharmony_ci 89e41f4b71Sopenharmony_ci The hardware device interface (HDI) is located between the basic system service layer and the device driver layer. It provides APIs for abstracting hardware device functions, which shield underlying hardware device differences for system services. For details, see [HDI Specifications](../../design/hdi-design-specifications.md). 90e41f4b71Sopenharmony_ci 91e41f4b71Sopenharmony_ci### Working Principles 92e41f4b71Sopenharmony_ci 93e41f4b71Sopenharmony_ciThe User_auth driver shields the differences of security devices and environments. It provides unified interfaces for the User_auth service to implement management of executors and credentials as well as authentication scheme generation. 94e41f4b71Sopenharmony_ciYou can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_ci**Figure 2** User_auth service and User_auth driver APIs 97e41f4b71Sopenharmony_ci 98e41f4b71Sopenharmony_ci 99e41f4b71Sopenharmony_ci 100e41f4b71Sopenharmony_ci### Constraints 101e41f4b71Sopenharmony_ci 102e41f4b71Sopenharmony_ciThe User_auth driver must be implemented in a TEE to ensure secure storage of user credentials and trustworthiness of user authentication results. 103e41f4b71Sopenharmony_ci 104e41f4b71Sopenharmony_ci## Development Guidelines 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci### When to Use 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ciThe User_auth driver provides stable user credential management, authentication session management, and executor information management for the User_auth service to ensure successful PIN authentication and biometric recognition on devices. 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci### Available APIs 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ciThe following table describes the C++ APIs generated from the Interface Definition Language (IDL) interface description. For details about the interface declaration, see the .idl file in **/drivers/interface/user_auth**. 113e41f4b71Sopenharmony_ci**Table 1** describes the HDI APIs for executor registration, credential enrollment and deletion, user authentication, and user identification. 114e41f4b71Sopenharmony_ci 115e41f4b71Sopenharmony_ci**Table 1** Available APIs 116e41f4b71Sopenharmony_ci 117e41f4b71Sopenharmony_ci| API | Description | 118e41f4b71Sopenharmony_ci| --------------------------- | --------------------------- | 119e41f4b71Sopenharmony_ci| Init() | Initializes cached information. | 120e41f4b71Sopenharmony_ci| AddExecutor(const HdiExecutorRegisterInfo &info, uint64_t &index, std::vector<uint8_t> &publicKey, std::vector<uint64_t> &templateIds) |Adds an executor to obtain the authentication capability.| 121e41f4b71Sopenharmony_ci| DeleteExecutor(uint64_t index) | Deletes an executor. | 122e41f4b71Sopenharmony_ci| OpenSession(int32_t userId, std::vector<uint8_t> &challenge) | Opens a session for authentication credential management. | 123e41f4b71Sopenharmony_ci| CloseSession(int32_t userId) | Closes a session for authentication credential management. | 124e41f4b71Sopenharmony_ci| BeginEnrollment(const std::vector<uint8_t> &authToken, const HdiEnrollParam ¶m, HdiScheduleInfo &info) | Enrolls the user authentication credential. If a user has enrolled a PIN, the old PIN will be overwritten. | 125e41f4b71Sopenharmony_ci| UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t> & scheduleResult, EnrollResultInfo &info)| Updates the data to complete this enrollment. | 126e41f4b71Sopenharmony_ci| CancelEnrollment(int32_t userId) | Cancels an enrollment. | 127e41f4b71Sopenharmony_ci| DeleteCredential(int32_t userId, uint64_t credentialId, const std::vector<uint8_t> &authToken, CredentialInfo &info) | Deletes credential information based on the specified **credentialId**. | 128e41f4b71Sopenharmony_ci| DeleteUser(int32_t userId, const std::vector<uint8_t> &authToken, std::vector<CredentialInfo> &deletedInfos, std::vector<uint8_t> &rootSecret) | Deletes a user PIN from User_auth. | 129e41f4b71Sopenharmony_ci| EnforceDeleteUser(int32_t userId, std::vector<CredentialInfo> &deletedInfos) | Forcibly deletes a user. This API will be called when a user is deleted from the system. | 130e41f4b71Sopenharmony_ci| GetCredential(int32_t userId, int32_t authType, std::vector<CredentialInfo> &infos) | Obtains user credential information by authentication type. | 131e41f4b71Sopenharmony_ci| BeginAuthentication(uint64_t contextId, const HdiAuthParam ¶m, std::vector<HdiScheduleInfo> &infos) | Starts an authentication to generate the authentication scheme and scheduling information. | 132e41f4b71Sopenharmony_ci| UpdateAuthenticationResult(uint64_t contextId, const std::vector<uint8_t> & scheduleResult, HdiAuthResultInfo &info, HdiEnrolledState &enrolledState)| Updates the authentication result to evaluate the authentication scheme. | 133e41f4b71Sopenharmony_ci| CancelAuthentication(uint64_t contextId) | Cancels an authentication. | 134e41f4b71Sopenharmony_ci| BeginIdentification(uint64_t contextId, int32_t authType, const std::vector<uint8_t> &challenge, uint32_t executorSensorHint, HdiScheduleInfo &scheduleInfo) | Starts an identification to generate the identification scheme and scheduling information. | 135e41f4b71Sopenharmony_ci| UpdateIdentificationResult(uint64_t contextId, const std::vector<uint8_t> &scheduleResult, IdentifyResultInfo &info) | Updates the identification result to evaluate the identification scheme. | 136e41f4b71Sopenharmony_ci| CancelIdentification(uint64_t contextId) | Cancels an identification. | 137e41f4b71Sopenharmony_ci| GetAuthTrustLevel(int32_t userId, int32_t authType, uint32_t &authTrustLevel) | Obtains the authentication trust level of the specified authentication type. | 138e41f4b71Sopenharmony_ci| GetValidSolution(int32_t userId, const std::vector<int32_t> &authTypes, uint32_t authTrustLevel, std::vector<int32_t> &validTypes) | Obtains the valid authentication scheme based on the authentication trust level for a user. | 139e41f4b71Sopenharmony_ci| GetAllUserInfo(std::vector<UserInfo> &userInfos) | Obtains all user information (excluding **userId**). | 140e41f4b71Sopenharmony_ci| GetUserInfo(int32_t userId, uint64_t &secureUid, int32_t &pinSubType, std::vector<EnrolledInfo> &infos) | Obtains user information. | 141e41f4b71Sopenharmony_ci| GetAllExtUserInfo(std::vector<ExtUserInfo> &userInfos) | Obtains all user information (including **userId**). | 142e41f4b71Sopenharmony_ci| GetEnrolledState(int32_t userId, int32_t authType, HdiEnrolledState &enrolledState) | Obtains enrollment information. | 143e41f4b71Sopenharmony_ci| CheckReuseUnlockResult(const ReuseUnlockParam& param, ReuseUnlockInfo& info) | Checks whether the device unlocking result is reused. | 144e41f4b71Sopenharmony_ci| SendMessage(uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t>& msg) | Sends messages to the executor. | 145e41f4b71Sopenharmony_ci| RegisterMessageCallback(const sptr<IMessageCallback>& messageCallback) | Registers a callback for executor messages.| 146e41f4b71Sopenharmony_ci| GetLocalScheduleFromMessage(const std::vector<uint8_t>& remoteDeviceId, const std::vector<uint8_t>& message, HdiScheduleInfo& scheduleInfo) | Obtains scheduling information of the local executor. | 147e41f4b71Sopenharmony_ci| GetSignedExecutorInfo(const std::vector<int32_t>& authTypes, int32_t executorRole, const std::vector<uint8_t>& remoteDeviceId, std::vector<uint8_t>& signedExecutorInfo) | Obtains information about the signed executor. | 148e41f4b71Sopenharmony_ci 149e41f4b71Sopenharmony_ci### How to Develop 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ciThe following uses the Hi3516D V300 development board as an example to demonstrate how to develop the User_auth driver. <br/>The directory structure is as follows: 152e41f4b71Sopenharmony_ci 153e41f4b71Sopenharmony_ci```undefined 154e41f4b71Sopenharmony_ci// drivers/peripheral/user_auth 155e41f4b71Sopenharmony_ci├── BUILD.gn # Build script 156e41f4b71Sopenharmony_ci├── bundle.json # Component description file 157e41f4b71Sopenharmony_ci└── hdi_service # User_auth driver implementation 158e41f4b71Sopenharmony_ci ├── BUILD.gn # Build script 159e41f4b71Sopenharmony_ci ├── module # Implementation of functionalities 160e41f4b71Sopenharmony_ci └── service 161e41f4b71Sopenharmony_ci ├── user_auth_interface_driver.cpp # User_auth driver entry 162e41f4b71Sopenharmony_ci └── user_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list 163e41f4b71Sopenharmony_ci``` 164e41f4b71Sopenharmony_ci 165e41f4b71Sopenharmony_ciThe development procedure is as follows: 166e41f4b71Sopenharmony_ci 167e41f4b71Sopenharmony_ci1. Develop the User_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [user_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_driver.cpp). 168e41f4b71Sopenharmony_ci 169e41f4b71Sopenharmony_ci ```c++ 170e41f4b71Sopenharmony_ci // Create an IRemoteObject object by using the custom HdfUserAuthInterfaceHost object, which consists of the IoService object and HDI service. 171e41f4b71Sopenharmony_ci struct HdfUserAuthInterfaceHost { 172e41f4b71Sopenharmony_ci struct IDeviceIoService ioService; 173e41f4b71Sopenharmony_ci OHOS::sptr<OHOS::IRemoteObject> stub; 174e41f4b71Sopenharmony_ci }; 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ci // Enable the IPC service to call the response API. 177e41f4b71Sopenharmony_ci static int32_t UserAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, 178e41f4b71Sopenharmony_ci struct HdfSBuf *reply) 179e41f4b71Sopenharmony_ci { 180e41f4b71Sopenharmony_ci auto *hdfUserAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfUserAuthInterfaceHost, ioService); 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci OHOS::MessageParcel *dataParcel = nullptr; 183e41f4b71Sopenharmony_ci OHOS::MessageParcel *replyParcel = nullptr; 184e41f4b71Sopenharmony_ci OHOS::MessageOption option; 185e41f4b71Sopenharmony_ci 186e41f4b71Sopenharmony_ci if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 187e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); 188e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 189e41f4b71Sopenharmony_ci } 190e41f4b71Sopenharmony_ci if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 191e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); 192e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 193e41f4b71Sopenharmony_ci } 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci return hdfUserAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 196e41f4b71Sopenharmony_ci } 197e41f4b71Sopenharmony_ci 198e41f4b71Sopenharmony_ci // Initialize the HdfUserAuthInterfaceDriver object. 199e41f4b71Sopenharmony_ci int HdfUserAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 200e41f4b71Sopenharmony_ci { 201e41f4b71Sopenharmony_ci HDF_LOGI("HdfUserAuthInterfaceDriverInit enter"); 202e41f4b71Sopenharmony_ci OHOS::UserIAM::Common::Init(); 203e41f4b71Sopenharmony_ci return HDF_SUCCESS; 204e41f4b71Sopenharmony_ci } 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci // Bind the service provided by the User_auth driver to the HDF. 207e41f4b71Sopenharmony_ci int HdfUserAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 208e41f4b71Sopenharmony_ci { 209e41f4b71Sopenharmony_ci HDF_LOGI("HdfUserAuthInterfaceDriverBind enter"); 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci auto *hdfUserAuthInterfaceHost = new (std::nothrow) HdfUserAuthInterfaceHost; 212e41f4b71Sopenharmony_ci if (hdfUserAuthInterfaceHost == nullptr) { 213e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: failed to create HdfUserAuthInterfaceHost object", __func__); 214e41f4b71Sopenharmony_ci return HDF_FAILURE; 215e41f4b71Sopenharmony_ci } 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ci hdfUserAuthInterfaceHost->ioService.Dispatch = UserAuthInterfaceDriverDispatch; 218e41f4b71Sopenharmony_ci hdfUserAuthInterfaceHost->ioService.Open = NULL; 219e41f4b71Sopenharmony_ci hdfUserAuthInterfaceHost->ioService.Release = NULL; 220e41f4b71Sopenharmony_ci 221e41f4b71Sopenharmony_ci auto serviceImpl = IUserAuthInterface::Get(true); 222e41f4b71Sopenharmony_ci if (serviceImpl == nullptr) { 223e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: failed to implement service", __func__); 224e41f4b71Sopenharmony_ci return HDF_FAILURE; 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci 227e41f4b71Sopenharmony_ci hdfUserAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 228e41f4b71Sopenharmony_ci IUserAuthInterface::GetDescriptor()); 229e41f4b71Sopenharmony_ci if (hdfUserAuthInterfaceHost->stub == nullptr) { 230e41f4b71Sopenharmony_ci HDF_LOGE("%{public}s: failed to get stub object", __func__); 231e41f4b71Sopenharmony_ci return HDF_FAILURE; 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci 234e41f4b71Sopenharmony_ci deviceObject->service = &hdfUserAuthInterfaceHost->ioService; 235e41f4b71Sopenharmony_ci return HDF_SUCCESS; 236e41f4b71Sopenharmony_ci } 237e41f4b71Sopenharmony_ci 238e41f4b71Sopenharmony_ci // Release resources of the User_auth driver. 239e41f4b71Sopenharmony_ci void HdfUserAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject){ 240e41f4b71Sopenharmony_ci HDF_LOGI("HdfUserAuthInterfaceDriverRelease enter"); 241e41f4b71Sopenharmony_ci auto *hdfUserAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfUserAuthInterfaceHost, ioService); 242e41f4b71Sopenharmony_ci delete hdfUserAuthInterfaceHost; 243e41f4b71Sopenharmony_ci } 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci // Register the User_auth driver entry data structure object. 246e41f4b71Sopenharmony_ci struct HdfDriverEntry g_userAuthInterfaceDriverEntry = { 247e41f4b71Sopenharmony_ci .moduleVersion = 1, 248e41f4b71Sopenharmony_ci .moduleName = "user_auth_device_driver", 249e41f4b71Sopenharmony_ci .Bind = HdfUserAuthInterfaceDriverBind, 250e41f4b71Sopenharmony_ci .Init = HdfUserAuthInterfaceDriverInit, 251e41f4b71Sopenharmony_ci .Release = HdfUserAuthInterfaceDriverRelease, 252e41f4b71Sopenharmony_ci }; 253e41f4b71Sopenharmony_ci 254e41f4b71Sopenharmony_ci // Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model. 255e41f4b71Sopenharmony_ci #ifndef __cplusplus 256e41f4b71Sopenharmony_ci extern "C" { 257e41f4b71Sopenharmony_ci #endif 258e41f4b71Sopenharmony_ci HDF_INIT(g_userAuthInterfaceDriverEntry); 259e41f4b71Sopenharmony_ci #ifndef __cplusplus 260e41f4b71Sopenharmony_ci } 261e41f4b71Sopenharmony_ci #endif 262e41f4b71Sopenharmony_ci ``` 263e41f4b71Sopenharmony_ci 264e41f4b71Sopenharmony_ci2. Register the executor. For details about the code, see [user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp). 265e41f4b71Sopenharmony_ci 266e41f4b71Sopenharmony_ci ```c++ 267e41f4b71Sopenharmony_ci // Add an executor. 268e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::AddExecutor(const HdiExecutorRegisterInfo &info, uint64_t &index, 269e41f4b71Sopenharmony_ci std::vector<uint8_t> &publicKey, std::vector<uint64_t> &templateIds) 270e41f4b71Sopenharmony_ci { 271e41f4b71Sopenharmony_ci GlobalLock(); 272e41f4b71Sopenharmony_ci ExecutorInfoHal executorInfoHal; 273e41f4b71Sopenharmony_ci CopyExecutorInfo(info, executorInfoHal); 274e41f4b71Sopenharmony_ci int32_t ret = RegisterExecutor(&executorInfoHal, &index); 275e41f4b71Sopenharmony_ci GlobalUnLock(); 276e41f4b71Sopenharmony_ci return ret; 277e41f4b71Sopenharmony_ci } 278e41f4b71Sopenharmony_ci 279e41f4b71Sopenharmony_ci // Delete the executor. 280e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::DeleteExecutor(uint64_t index) 281e41f4b71Sopenharmony_ci { 282e41f4b71Sopenharmony_ci return UnRegisterExecutor(index); 283e41f4b71Sopenharmony_ci } 284e41f4b71Sopenharmony_ci ``` 285e41f4b71Sopenharmony_ci 286e41f4b71Sopenharmony_ci3. Enroll user authentication data. For details about the code, see [user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp). 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci ```c++ 289e41f4b71Sopenharmony_ci // Open a session for authentication credential management. 290e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::OpenSession(int32_t userId, std::vector<uint8_t>& challenge) 291e41f4b71Sopenharmony_ci { 292e41f4b71Sopenharmony_ci GlobalLock(); 293e41f4b71Sopenharmony_ci uint64_t challengeU64 = 0; 294e41f4b71Sopenharmony_ci int32_t ret = OpenEditSession(userId, &challengeU64); 295e41f4b71Sopenharmony_ci challenge.resize(sizeof(uint64_t)); 296e41f4b71Sopenharmony_ci if (memcpy_s(&challenge[0], challenge.size(), &challengeU64, sizeof(uint64_t)) != EOK) { 297e41f4b71Sopenharmony_ci IAM_LOGE("failed to copy challengeU64"); 298e41f4b71Sopenharmony_ci return RESULT_BAD_COPY; 299e41f4b71Sopenharmony_ci } 300e41f4b71Sopenharmony_ci GlobalUnLock(); 301e41f4b71Sopenharmony_ci return ret; 302e41f4b71Sopenharmony_ci } 303e41f4b71Sopenharmony_ci 304e41f4b71Sopenharmony_ci // Close the session for authentication credential management. 305e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::CloseSession(int32_t userId) 306e41f4b71Sopenharmony_ci { 307e41f4b71Sopenharmony_ci GlobalLock(); 308e41f4b71Sopenharmony_ci int32_t ret = CloseEditSession(); 309e41f4b71Sopenharmony_ci GlobalUnLock(); 310e41f4b71Sopenharmony_ci return ret; 311e41f4b71Sopenharmony_ci } 312e41f4b71Sopenharmony_ci 313e41f4b71Sopenharmony_ci // Start enrollment to generate enrollment and scheduling information. 314e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::BeginEnrollment( 315e41f4b71Sopenharmony_ci const std::vector<uint8_t> &authToken, const HdiEnrollParam ¶m, HdiScheduleInfo &info) 316e41f4b71Sopenharmony_ci { 317e41f4b71Sopenharmony_ci IAM_LOGI("start"); 318e41f4b71Sopenharmony_ci GlobalLock(); 319e41f4b71Sopenharmony_ci if (authToken.size() != sizeof(UserAuthTokenHal) && param.authType != PIN) { 320e41f4b71Sopenharmony_ci IAM_LOGE("authToken len is invalid"); 321e41f4b71Sopenharmony_ci GlobalUnLock(); 322e41f4b71Sopenharmony_ci return RESULT_BAD_PARAM; 323e41f4b71Sopenharmony_ci } 324e41f4b71Sopenharmony_ci PermissionCheckParam checkParam; 325e41f4b71Sopenharmony_ci if (authToken.size() == sizeof(UserAuthTokenHal) && 326e41f4b71Sopenharmony_ci memcpy_s(checkParam.token, AUTH_TOKEN_LEN, &authToken[0], authToken.size()) != EOK) { 327e41f4b71Sopenharmony_ci GlobalUnLock(); 328e41f4b71Sopenharmony_ci return RESULT_BAD_COPY; 329e41f4b71Sopenharmony_ci } 330e41f4b71Sopenharmony_ci checkParam.authType = param.authType; 331e41f4b71Sopenharmony_ci checkParam.userId = userId; 332e41f4b71Sopenharmony_ci checkParam.authSubType = (uint64_t)param.executorType; 333e41f4b71Sopenharmony_ci CoAuthSchedule scheduleInfo; 334e41f4b71Sopenharmony_ci int32_t ret = CheckEnrollPermission(checkParam, &scheduleInfo.scheduleId); 335e41f4b71Sopenharmony_ci if (ret != RESULT_SUCCESS) { 336e41f4b71Sopenharmony_ci IAM_LOGE("Failed to check permission"); 337e41f4b71Sopenharmony_ci GlobalUnLock(); 338e41f4b71Sopenharmony_ci return ret; 339e41f4b71Sopenharmony_ci } 340e41f4b71Sopenharmony_ci ret = GetCoAuthSchedule(&scheduleInfo); 341e41f4b71Sopenharmony_ci if (ret != RESULT_SUCCESS) { 342e41f4b71Sopenharmony_ci IAM_LOGE("Failed to get schedule info"); 343e41f4b71Sopenharmony_ci GlobalUnLock(); 344e41f4b71Sopenharmony_ci return ret; 345e41f4b71Sopenharmony_ci } 346e41f4b71Sopenharmony_ci if (!CopyScheduleInfo(&scheduleInfo, &info)) { 347e41f4b71Sopenharmony_ci IAM_LOGE("Failed to copy schedule info"); 348e41f4b71Sopenharmony_ci ret = RESULT_BAD_COPY; 349e41f4b71Sopenharmony_ci } 350e41f4b71Sopenharmony_ci GlobalUnLock(); 351e41f4b71Sopenharmony_ci return ret; 352e41f4b71Sopenharmony_ci } 353e41f4b71Sopenharmony_ci 354e41f4b71Sopenharmony_ci // Cancel the enrollment. 355e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::CancelEnrollment(int32_t userId) 356e41f4b71Sopenharmony_ci { 357e41f4b71Sopenharmony_ci IAM_LOGI("start"); 358e41f4b71Sopenharmony_ci BreakOffCoauthSchedule(userId); 359e41f4b71Sopenharmony_ci return RESULT_SUCCESS; 360e41f4b71Sopenharmony_ci } 361e41f4b71Sopenharmony_ci 362e41f4b71Sopenharmony_ci // Update the enrolled credential information. 363e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t> &scheduleResult, EnrollResultInfo &info) 364e41f4b71Sopenharmony_ci { 365e41f4b71Sopenharmony_ci IAM_LOGI("start"); 366e41f4b71Sopenharmony_ci GlobalLock(); 367e41f4b71Sopenharmony_ci if (scheduleResult.size() == 0) { 368e41f4b71Sopenharmony_ci IAM_LOGE("enrollToken is invalid"); 369e41f4b71Sopenharmony_ci GlobalUnLock(); 370e41f4b71Sopenharmony_ci return RESULT_BAD_PARAM; 371e41f4b71Sopenharmony_ci } 372e41f4b71Sopenharmony_ci Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 373e41f4b71Sopenharmony_ci if (scheduleResultBuffer == nullptr) { 374e41f4b71Sopenharmony_ci IAM_LOGE("scheduleTokenBuffer is null"); 375e41f4b71Sopenharmony_ci GlobalUnLock(); 376e41f4b71Sopenharmony_ci return RESULT_NO_MEMORY; 377e41f4b71Sopenharmony_ci } 378e41f4b71Sopenharmony_ci bool isUpdate; 379e41f4b71Sopenharmony_ci int32_t ret = GetIsUpdate(&isUpdate); 380e41f4b71Sopenharmony_ci if (ret != RESULT_SUCCESS) { 381e41f4b71Sopenharmony_ci IAM_LOGE("Failed to get isUpdate"); 382e41f4b71Sopenharmony_ci return ret; 383e41f4b71Sopenharmony_ci } 384e41f4b71Sopenharmony_ci if (isUpdate) { 385e41f4b71Sopenharmony_ci CredentialInfoHal oldCredentialHal; 386e41f4b71Sopenharmony_ci ret = UpdateCredentialFunc(scheduleResultBuffer, &credentialId, &oldCredentialHal); 387e41f4b71Sopenharmony_ci oldInfo.authType = static_cast<AuthType>(oldCredentialHal.authType); 388e41f4b71Sopenharmony_ci oldInfo.credentialId = oldCredentialHal.credentialId; 389e41f4b71Sopenharmony_ci oldInfo.templateId = oldCredentialHal.templateId; 390e41f4b71Sopenharmony_ci oldInfo.executorType = static_cast<uint32_t>(oldCredentialHal.authSubType); 391e41f4b71Sopenharmony_ci oldInfo.executorId = 0; 392e41f4b71Sopenharmony_ci oldInfo.index = 0; 393e41f4b71Sopenharmony_ci } else { 394e41f4b71Sopenharmony_ci ret = AddCredentialFunc(scheduleResultBuffer, &credentialId); 395e41f4b71Sopenharmony_ci } 396e41f4b71Sopenharmony_ci DestoryBuffer(scheduleResultBuffer); 397e41f4b71Sopenharmony_ci GlobalUnLock(); 398e41f4b71Sopenharmony_ci return ret; 399e41f4b71Sopenharmony_ci } 400e41f4b71Sopenharmony_ci ``` 401e41f4b71Sopenharmony_ci 402e41f4b71Sopenharmony_ci4. Perform the authentication. For details about the code, see [user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp). 403e41f4b71Sopenharmony_ci 404e41f4b71Sopenharmony_ci ```c++ 405e41f4b71Sopenharmony_ci // Create an HDI service object. 406e41f4b71Sopenharmony_ci extern "C" IUserAuthInterface *UserAuthInterfaceImplGetInstance(void) 407e41f4b71Sopenharmony_ci { 408e41f4b71Sopenharmony_ci auto userAuthInterfaceService = new (std::nothrow) UserAuthInterfaceService(); 409e41f4b71Sopenharmony_ci if (userAuthInterfaceService == nullptr) { 410e41f4b71Sopenharmony_ci IAM_LOGE("userAuthInterfaceService is nullptr"); 411e41f4b71Sopenharmony_ci return nullptr; 412e41f4b71Sopenharmony_ci } 413e41f4b71Sopenharmony_ci return userAuthInterfaceService; 414e41f4b71Sopenharmony_ci } 415e41f4b71Sopenharmony_ci 416e41f4b71Sopenharmony_ci // Start an authentication to generate the authentication scheme and scheduling information. 417e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::BeginAuthentication(uint64_t contextId, const HdiAuthParam ¶m, 418e41f4b71Sopenharmony_ci std::vector<HdiScheduleInfo> &infos) 419e41f4b71Sopenharmony_ci { 420e41f4b71Sopenharmony_ci IAM_LOGI("start"); 421e41f4b71Sopenharmony_ci if (param.challenge.size() != sizeof(uint64_t)) { 422e41f4b71Sopenharmony_ci IAM_LOGE("Failed to copy challenge"); 423e41f4b71Sopenharmony_ci return RESULT_BAD_PARAM; 424e41f4b71Sopenharmony_ci } 425e41f4b71Sopenharmony_ci GlobalLock(); 426e41f4b71Sopenharmony_ci CoAuthSchedule *schedulesGet = nullptr; 427e41f4b71Sopenharmony_ci uint32_t scheduleIdNum = 0; 428e41f4b71Sopenharmony_ci AuthSolutionHal solutionIn; 429e41f4b71Sopenharmony_ci solutionIn.contextId = contextId; 430e41f4b71Sopenharmony_ci solutionIn.userId = param.userId; 431e41f4b71Sopenharmony_ci solutionIn.authType = static_cast<uint32_t>(param.authType); 432e41f4b71Sopenharmony_ci solutionIn.authTrustLevel = param.authTrustLevel; 433e41f4b71Sopenharmony_ci if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), ¶m.challenge[0], 434e41f4b71Sopenharmony_ci param.challenge.size()) != EOK) { 435e41f4b71Sopenharmony_ci IAM_LOGE("Failed to copy challenge"); 436e41f4b71Sopenharmony_ci GlobalUnLock(); 437e41f4b71Sopenharmony_ci return RESULT_BAD_COPY; 438e41f4b71Sopenharmony_ci } 439e41f4b71Sopenharmony_ci int32_t ret = GenerateSolutionFunc(solutionIn, &schedulesGet, &scheduleIdNum); 440e41f4b71Sopenharmony_ci if (ret != RESULT_SUCCESS) { 441e41f4b71Sopenharmony_ci IAM_LOGE("Failed to generate solution"); 442e41f4b71Sopenharmony_ci GlobalUnLock(); 443e41f4b71Sopenharmony_ci return ret; 444e41f4b71Sopenharmony_ci } 445e41f4b71Sopenharmony_ci for (uint32_t i = 0; i < scheduleIdNum; i++) { 446e41f4b71Sopenharmony_ci ScheduleInfoV1_1 temp; 447e41f4b71Sopenharmony_ci if (!CopyScheduleInfo(schedulesGet + i, &temp)) { 448e41f4b71Sopenharmony_ci infos.clear(); 449e41f4b71Sopenharmony_ci ret = RESULT_GENERAL_ERROR; 450e41f4b71Sopenharmony_ci break; 451e41f4b71Sopenharmony_ci } 452e41f4b71Sopenharmony_ci infos.push_back(temp); 453e41f4b71Sopenharmony_ci } 454e41f4b71Sopenharmony_ci free(schedulesGet); 455e41f4b71Sopenharmony_ci GlobalUnLock(); 456e41f4b71Sopenharmony_ci return ret; 457e41f4b71Sopenharmony_ci } 458e41f4b71Sopenharmony_ci 459e41f4b71Sopenharmony_ci // Update the authentication result to evaluate the authentication scheme. 460e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::UpdateAuthenticationResult(uint64_t contextId, 461e41f4b71Sopenharmony_ci const std::vector<uint8_t> &scheduleResult, HdiAuthResultInfo &info, HdiEnrolledState &enrolledState) 462e41f4b71Sopenharmony_ci { 463e41f4b71Sopenharmony_ci IAM_LOGI("start"); 464e41f4b71Sopenharmony_ci GlobalLock(); 465e41f4b71Sopenharmony_ci if (scheduleResult.size() == 0) { 466e41f4b71Sopenharmony_ci IAM_LOGE("param is invalid"); 467e41f4b71Sopenharmony_ci info.result = RESULT_BAD_PARAM; 468e41f4b71Sopenharmony_ci GlobalUnLock(); 469e41f4b71Sopenharmony_ci return RESULT_BAD_PARAM; 470e41f4b71Sopenharmony_ci } 471e41f4b71Sopenharmony_ci Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 472e41f4b71Sopenharmony_ci if (scheduleResultBuffer == nullptr) { 473e41f4b71Sopenharmony_ci IAM_LOGE("scheduleTokenBuffer is null"); 474e41f4b71Sopenharmony_ci info.result = RESULT_GENERAL_ERROR; 475e41f4b71Sopenharmony_ci GlobalUnLock(); 476e41f4b71Sopenharmony_ci return RESULT_NO_MEMORY; 477e41f4b71Sopenharmony_ci } 478e41f4b71Sopenharmony_ci UserAuthTokenHal authTokenHal; 479e41f4b71Sopenharmony_ci info.result = RequestAuthResultFunc(contextId, scheduleResultBuffer, &authTokenHal); 480e41f4b71Sopenharmony_ci if (info.result != RESULT_SUCCESS) { 481e41f4b71Sopenharmony_ci IAM_LOGE("Failed to execute func"); 482e41f4b71Sopenharmony_ci DestoryBuffer(scheduleResultBuffer); 483e41f4b71Sopenharmony_ci GlobalUnLock(); 484e41f4b71Sopenharmony_ci return info.result; 485e41f4b71Sopenharmony_ci } 486e41f4b71Sopenharmony_ci info.token.resize(sizeof(UserAuthTokenHal)); 487e41f4b71Sopenharmony_ci if (memcpy_s(&info.token[0], info.token.size(), &authTokenHal, sizeof(authTokenHal)) != EOK) { 488e41f4b71Sopenharmony_ci IAM_LOGE("Failed to copy authToken"); 489e41f4b71Sopenharmony_ci DestoryBuffer(scheduleResultBuffer); 490e41f4b71Sopenharmony_ci GlobalUnLock(); 491e41f4b71Sopenharmony_ci return RESULT_BAD_COPY; 492e41f4b71Sopenharmony_ci } 493e41f4b71Sopenharmony_ci DestoryBuffer(scheduleResultBuffer); 494e41f4b71Sopenharmony_ci GlobalUnLock(); 495e41f4b71Sopenharmony_ci return RESULT_SUCCESS; 496e41f4b71Sopenharmony_ci } 497e41f4b71Sopenharmony_ci 498e41f4b71Sopenharmony_ci // Cancel the authentication. 499e41f4b71Sopenharmony_ci int32_t UserAuthInterfaceService::CancelAuthentication(uint64_t contextId) 500e41f4b71Sopenharmony_ci { 501e41f4b71Sopenharmony_ci IAM_LOGI("start"); 502e41f4b71Sopenharmony_ci GlobalLock(); 503e41f4b71Sopenharmony_ci uint32_t scheduleIdNum = 0; 504e41f4b71Sopenharmony_ci int32_t ret = CancelContextFunc(contextId, nullptr, &scheduleIdNum); 505e41f4b71Sopenharmony_ci if (ret != RESULT_SUCCESS) { 506e41f4b71Sopenharmony_ci IAM_LOGE("Failed to execute func"); 507e41f4b71Sopenharmony_ci GlobalUnLock(); 508e41f4b71Sopenharmony_ci return ret; 509e41f4b71Sopenharmony_ci } 510e41f4b71Sopenharmony_ci GlobalUnLock(); 511e41f4b71Sopenharmony_ci return RESULT_SUCCESS; 512e41f4b71Sopenharmony_ci } 513e41f4b71Sopenharmony_ci ``` 514e41f4b71Sopenharmony_ci 515e41f4b71Sopenharmony_ci### Verification 516e41f4b71Sopenharmony_ci 517e41f4b71Sopenharmony_ciUse the [User Authentication APIs](../../application-dev/reference/apis-user-authentication-kit/js-apis-useriam-userauth.md) to develop a HAP and verify the application on the RK3568 platform. 518e41f4b71Sopenharmony_ci 519e41f4b71Sopenharmony_ci1. Initiate a request for user authentication and obtain the authentication result. 520e41f4b71Sopenharmony_ci 521e41f4b71Sopenharmony_ci```ts 522e41f4b71Sopenharmony_ci // API version 10 523e41f4b71Sopenharmony_ci import type {BusinessError} from '@ohos.base'; 524e41f4b71Sopenharmony_ci import userIAM_userAuth from '@ohos.userIAM.userAuth'; 525e41f4b71Sopenharmony_ci 526e41f4b71Sopenharmony_ci // Set authentication parameters. 527e41f4b71Sopenharmony_ci const authParam: userIAM_userAuth.AuthParam = { 528e41f4b71Sopenharmony_ci challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 529e41f4b71Sopenharmony_ci authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 530e41f4b71Sopenharmony_ci authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 531e41f4b71Sopenharmony_ci }; 532e41f4b71Sopenharmony_ci // Set the authentication page. 533e41f4b71Sopenharmony_ci const widgetParam: userIAM_userAuth.WidgetParam = { 534e41f4b71Sopenharmony_ci title: 'Verify identity', 535e41f4b71Sopenharmony_ci }; 536e41f4b71Sopenharmony_ci try { 537e41f4b71Sopenharmony_ci // Obtain an authentication object. 538e41f4b71Sopenharmony_ci let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 539e41f4b71Sopenharmony_ci console.info('get userAuth instance success'); 540e41f4b71Sopenharmony_ci // Subscribe to the authentication result. 541e41f4b71Sopenharmony_ci userAuthInstance.on('result', { 542e41f4b71Sopenharmony_ci onResult(result) { 543e41f4b71Sopenharmony_ci console.info(`userAuthInstance callback result: ${JSON.stringify(result)}`); 544e41f4b71Sopenharmony_ci // Unsubscribe from the authentication result if required. 545e41f4b71Sopenharmony_ci userAuthInstance.off('result'); 546e41f4b71Sopenharmony_ci } 547e41f4b71Sopenharmony_ci }); 548e41f4b71Sopenharmony_ci console.info('auth on success'); 549e41f4b71Sopenharmony_ci userAuthInstance.start(); 550e41f4b71Sopenharmony_ci console.info('auth start success'); 551e41f4b71Sopenharmony_ci } catch (error) { 552e41f4b71Sopenharmony_ci const err: BusinessError = error as BusinessError; 553e41f4b71Sopenharmony_ci console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 554e41f4b71Sopenharmony_ci } 555e41f4b71Sopenharmony_ci``` 556e41f4b71Sopenharmony_ci 557e41f4b71Sopenharmony_ci2. Cancel an authentication. 558e41f4b71Sopenharmony_ci 559e41f4b71Sopenharmony_ci```ts 560e41f4b71Sopenharmony_ci // API version 10 561e41f4b71Sopenharmony_ci import type {BusinessError} from '@ohos.base'; 562e41f4b71Sopenharmony_ci import userIAM_userAuth from '@ohos.userIAM.userAuth'; 563e41f4b71Sopenharmony_ci 564e41f4b71Sopenharmony_ci const authParam: userIAM_userAuth.AuthParam = { 565e41f4b71Sopenharmony_ci challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 566e41f4b71Sopenharmony_ci authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 567e41f4b71Sopenharmony_ci authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 568e41f4b71Sopenharmony_ci }; 569e41f4b71Sopenharmony_ci const widgetParam: userIAM_userAuth.WidgetParam = { 570e41f4b71Sopenharmony_ci title: 'Verify identity', 571e41f4b71Sopenharmony_ci }; 572e41f4b71Sopenharmony_ci try { 573e41f4b71Sopenharmony_ci // Obtain an authentication object. 574e41f4b71Sopenharmony_ci let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 575e41f4b71Sopenharmony_ci console.info('get userAuth instance success'); 576e41f4b71Sopenharmony_ci // Start user authentication. 577e41f4b71Sopenharmony_ci userAuthInstance.start(); 578e41f4b71Sopenharmony_ci console.info('auth start success'); 579e41f4b71Sopenharmony_ci // Cancel the authentication. 580e41f4b71Sopenharmony_ci userAuthInstance.cancel(); 581e41f4b71Sopenharmony_ci console.info('auth cancel success'); 582e41f4b71Sopenharmony_ci } catch (error) { 583e41f4b71Sopenharmony_ci const err: BusinessError = error as BusinessError; 584e41f4b71Sopenharmony_ci console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 585e41f4b71Sopenharmony_ci } 586e41f4b71Sopenharmony_ci``` 587