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![image](figures/user_auth_architecture.png "User Authentication Architecture")
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![image](figures/user_auth_service_and_driver_api.png "Interaction")
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 &param, 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 &param, 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 &param, 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 &param,
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), &param.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