• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# User Authentication
2
3## Overview
4
5### Function
6
7User 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.
8
9The 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.
10
11**Figure 1** User authentication architecture
12
13![image](figures/user_auth_architecture.png "User authentication architecture")
14
15### Basic Concepts
16The 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.
17
18- Authentication credential information
19
20  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.
21
22- Authentication credential template
23
24  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.
25
26- Executor
27
28  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.
29
30- Executor role
31
32  - 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.
33
34  - Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication.
35
36  - Authenticator: processes data, obtains the stored credential template, and compares it with the authentication information generated.
37
38- Executor type
39
40  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.
41
42- Executor security level
43
44  Security level of the runtime environment when an executor provides capabilities.
45
46- User_auth public key & executor public key
47
48  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.
49
50    - 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.
51
52    - User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor.
53
54
55- Authentication result trust level
56
57  The trust level of the authentication result varies, depending on the authentication mode and the security level of the authentication execution environment.
58
59- Authentication scheme
60
61  An authentication scheme contains information about the authentication mode, trust level of the authentication result, executor, and credential.
62
63- Scheduling information
64
65  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.
66
67- SA
68
69  SAs are loaded by the System Ability Manager to provide basic system capabilities for OpenHarmony devices.
70
71- Kit
72
73  The kit provides basic APIs for third-party applications.
74
75- Inner API
76
77  Inner API is an API provided by OpenHarmony for system applications.
78
79- IDL interface
80
81  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).
82
83- IPC
84
85  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).
86
87- HDI
88
89  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 shields underlying hardware device differences for system services. For details, see [HDI Specifications](../../design/hdi-design-specifications.md).
90
91### Working Principles
92
93The 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.
94You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use.
95
96**Figure 2** User_auth service and User_auth driver APIs
97
98![image](figures/user_auth_service_and_driver_api.png "Interaction")
99
100### Constraints
101
102The User_auth driver must be implemented in a Trusted Execution Environment (TEE) to ensure secure storage of user credentials and trustworthiness of user authentication results.
103
104## Development Guidelines
105
106### When to Use
107
108The 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.
109
110### Available APIs
111
112The 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**.
113**Table 1** describes the HDI APIs for executor registration, credential enrollment and deletion, user authentication, and user identification.
114
115**Table 1** Available APIs
116
117| API      | Description    |
118| --------------------------- | --------------------------- |
119| Init()           | Initializes cached information.                       |
120| AddExecutor(const ExecutorRegisterInfo& info, uint64_t& index, std::vector\<uint8_t>& publicKey,<br>        std::vector\<uint64_t>& templateIds) | Adds an executor to obtain the authentication capability.          |
121| DeleteExecutor(uint64_t index)            | Deletes an executor.      |
122| OpenSession(int32_t userId, std::vector\<uint8_t>& challenge) | Opens a session for authentication credential management.     |
123| CloseSession(int32_t userId)        | Closes a session for authentication credential management.           |
124| BeginEnrollment(int32_t userId, const std::vector\<uint8_t>& authToken, const EnrollParam& param,<br>        ScheduleInfo& info) | Enrolls the user authentication credential (version V1_0). If a user has enrolled a PIN, the old PIN will be overwritten .|
125| UpdateEnrollmentResult(int32_t userId, const std::vector\<uint8_t>& scheduleResult, uint64_t& credentialId,<br>        CredentialInfo& oldInfo) | Updates the data to complete this enrollment.  |
126| CancelEnrollment(int32_t userId)     | Cancels an enrollment operation.         |
127| DeleteCredential(int32_t userId, uint64_t credentialId, const std::vector\<uint8_t>& authToken,<br>        CredentialInfo& info) | Deletes credential information based on the specified **credentialId**.                              |
128| DeleteUser(int32_t userId, const std::vector\<uint8_t>& authToken,<br>        std::vector\<CredentialInfo>& deletedInfos) | Deletes a user PIN from User_auth.                       |
129| 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.              |
130| GetCredential(int32_t userId, AuthType authType, std::vector\<CredentialInfo>& infos) | Obtains user credential information by authentication type.            |
131| GetSecureInfo(int32_t userId, uint64_t& secureUid, std::vector\<EnrolledInfo>& infos) | Obtains the secure user ID and the enrolled tag ID of each authentication type.            |
132| BeginAuthentication(uint64_t contextId, const AuthSolution& param,<br>        std::vector\<ScheduleInfo>& scheduleInfos) | Starts authentication and generates the authentication scheme and scheduling information (version V1_0).                          |
133| UpdateAuthenticationResult(uint64_t contextId, const std::vector\<uint8_t>& scheduleResult,<br>        AuthResultInfo& info) | Updates the authentication result to evaluate the authentication scheme.                  |
134| CancelAuthentication(uint64_t contextId)      | Cancels an authentication.            |
135| BeginIdentification(uint64_t contextId, AuthType authType, const std::vector\<int8_t>& challenge,<br>        uint32_t executorId, ScheduleInfo& scheduleInfo) | Starts identification and generates the identification scheme and scheduling information (version V1_0).                          |
136| UpdateIdentificationResult(uint64_t contextId, const std::vector\<uint8_t>& scheduleResult,<br>        IdentifyResultInfo& info) | Updates the identification result to evaluate the identification scheme.                  |
137| CancelIdentification(uint64_t contextId)             | Cancels an identification.             |
138| GetAuthTrustLevel(int32_t userId, AuthType authType, uint32_t& authTrustLevel) | Obtains the authentication trust level of the specified authentication type.    |
139| GetValidSolution(int32_t userId, const std::vector\<AuthType>& authTypes, uint32_t authTrustLevel,<br>        std::vector\<AuthType>& validTypes) | Obtains the valid authentication scheme based on the authentication trust level for a user.                  |
140| BeginEnrollmentV1_1(int32_t userId, const std::vector\<uint8_t>& authToken, const EnrollParam& param, ScheduleInfoV1_1& info) | Enrolls the user authentication credential (version V1_1). If a user has enrolled a PIN, the old PIN will be overwritten.|
141| BeginAuthenticationV1_1(uint64_t contextId, const AuthSolution& param,  std::vector\<ScheduleInfoV1_1>& scheduleInfos) | Starts authentication and generates the authentication scheme and scheduling information (version V1_1).                          |
142| BeginIdentificationV1_1(uint64_t contextId, AuthType authType,<br/> const std::vector\<uint8_t>& challenge, uint32_t executorSensorHint, ScheduleInfoV1_1& scheduleInfo) | Starts identification and generates the identification scheme and scheduling information (version V1_1). |
143### How to Develop
144
145The 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:
146
147```undefined
148// drivers/peripheral/user_auth
149├── BUILD.gn     # Build script
150├── bundle.json  # Component description file
151└── hdi_service  # User_auth driver implementation
152    ├── BUILD.gn # Build script
153    ├── module   # Implementation of functionalities
154    └── service
155        ├── user_auth_interface_driver.cpp  # User_auth driver entry
156        └── user_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list
157```
158
159The development procedure is as follows:
160
1611. 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).
162
163   ```c++
164   // Create an IRemoteObject object by using the custom HdfUserAuthInterfaceHost object, which consists of the IoService object and HDI service.
165   struct HdfUserAuthInterfaceHost {
166       struct IDeviceIoService ioService;
167       OHOS::sptr<OHOS::IRemoteObject> stub;
168   };
169
170   // Enable the IPC service to call the response API.
171   static int32_t UserAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
172       struct HdfSBuf *reply)
173   {
174       auto *hdfUserAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfUserAuthInterfaceHost, ioService);
175
176       OHOS::MessageParcel *dataParcel = nullptr;
177       OHOS::MessageParcel *replyParcel = nullptr;
178       OHOS::MessageOption option;
179
180       if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
181           HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
182           return HDF_ERR_INVALID_PARAM;
183       }
184       if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
185           HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
186           return HDF_ERR_INVALID_PARAM;
187       }
188
189       return hdfUserAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
190   }
191
192   // Initialize the HdfUserAuthInterfaceDriver object.
193   int HdfUserAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
194   {
195       HDF_LOGI("HdfUserAuthInterfaceDriverInit enter");
196       OHOS::UserIAM::Common::Init();
197       return HDF_SUCCESS;
198   }
199
200   // Bind the service provided by the User_auth driver to the HDF.
201   int HdfUserAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
202   {
203       HDF_LOGI("HdfUserAuthInterfaceDriverBind enter");
204
205       auto *hdfUserAuthInterfaceHost = new (std::nothrow) HdfUserAuthInterfaceHost;
206       if (hdfUserAuthInterfaceHost == nullptr) {
207           HDF_LOGE("%{public}s: failed to create HdfUserAuthInterfaceHost object", __func__);
208           return HDF_FAILURE;
209       }
210
211       hdfUserAuthInterfaceHost->ioService.Dispatch = UserAuthInterfaceDriverDispatch;
212       hdfUserAuthInterfaceHost->ioService.Open = NULL;
213       hdfUserAuthInterfaceHost->ioService.Release = NULL;
214
215       auto serviceImpl = IUserAuthInterface::Get(true);
216       if (serviceImpl == nullptr) {
217           HDF_LOGE("%{public}s: failed to implement service", __func__);
218           return HDF_FAILURE;
219       }
220
221       hdfUserAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
222           IUserAuthInterface::GetDescriptor());
223       if (hdfUserAuthInterfaceHost->stub == nullptr) {
224           HDF_LOGE("%{public}s: failed to get stub object", __func__);
225           return HDF_FAILURE;
226       }
227
228       deviceObject->service = &hdfUserAuthInterfaceHost->ioService;
229       return HDF_SUCCESS;
230   }
231
232   // Release resources of the User_auth driver.
233   void HdfUserAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject){
234       HDF_LOGI("HdfUserAuthInterfaceDriverRelease enter");
235       auto *hdfUserAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfUserAuthInterfaceHost, ioService);
236       delete hdfUserAuthInterfaceHost;
237   }
238
239   // Register the User_auth driver entry data structure object.
240   struct HdfDriverEntry g_userAuthInterfaceDriverEntry = {
241       .moduleVersion = 1,
242       .moduleName = "user_auth_device_driver",
243       .Bind = HdfUserAuthInterfaceDriverBind,
244       .Init = HdfUserAuthInterfaceDriverInit,
245       .Release = HdfUserAuthInterfaceDriverRelease,
246   };
247
248   // 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.
249   #ifndef __cplusplus
250   extern "C" {
251   #endif
252   HDF_INIT(g_userAuthInterfaceDriverEntry);
253   #ifndef __cplusplus
254   }
255   #endif
256   ```
257
2582. 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).
259
260   ```c++
261   // Add an executor.
262   int32_t UserAuthInterfaceService::AddExecutor(const ExecutorRegisterInfo& info, uint64_t& index,
263       std::vector<uint8_t>& publicKey, std::vector<uint64_t>& templateIds)
264   {
265       GlobalLock();
266       ExecutorInfoHal executorInfoHal;
267       CopyExecutorInfo(info, executorInfoHal);
268       int32_t ret = RegisterExecutor(&executorInfoHal, &index);
269       GlobalUnLock();
270       return ret;
271   }
272
273   // Delete the executor.
274   int32_t UserAuthInterfaceService::DeleteExecutor(uint64_t index)
275   {
276       return UnRegisterExecutor(index);
277   }
278   ```
279
2803. 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).
281
282   ```c++
283   // Open a session for authentication credential management.
284   int32_t UserAuthInterfaceService::OpenSession(int32_t userId, std::vector<uint8_t>& challenge)
285   {
286       GlobalLock();
287       uint64_t challengeU64 = 0;
288       int32_t ret = OpenEditSession(userId, &challengeU64);
289       challenge.resize(sizeof(uint64_t));
290       if (memcpy_s(&challenge[0], challenge.size(), &challengeU64, sizeof(uint64_t)) != EOK) {
291           IAM_LOGE("failed to copy challengeU64");
292           return RESULT_BAD_COPY;
293       }
294       GlobalUnLock();
295       return ret;
296   }
297
298   // Close the session for authentication credential management.
299   int32_t UserAuthInterfaceService::CloseSession(int32_t userId)
300   {
301       GlobalLock();
302       int32_t ret = CloseEditSession();
303       GlobalUnLock();
304       return ret;
305   }
306
307   // Start enrollment and generate scheduling information (V1_1).
308   int32_t UserAuthInterfaceService::BeginEnrollmentV1_1(int32_t userId, const std::vector<uint8_t>& authToken,
309       const EnrollParam& param, ScheduleInfoV1_1& info)
310   {
311       IAM_LOGI("start");
312       GlobalLock();
313       if (authToken.size() != sizeof(UserAuthTokenHal) && param.authType != PIN) {
314           IAM_LOGE("authToken len is invalid");
315           GlobalUnLock();
316           return RESULT_BAD_PARAM;
317       }
318       PermissionCheckParam checkParam;
319       if (authToken.size() == sizeof(UserAuthTokenHal) &&
320           memcpy_s(checkParam.token, AUTH_TOKEN_LEN, &authToken[0], authToken.size()) != EOK) {
321           GlobalUnLock();
322           return RESULT_BAD_COPY;
323       }
324       checkParam.authType = param.authType;
325       checkParam.userId = userId;
326       checkParam.authSubType = (uint64_t)param.executorType;
327       CoAuthSchedule scheduleInfo;
328       int32_t ret = CheckEnrollPermission(checkParam, &scheduleInfo.scheduleId);
329       if (ret != RESULT_SUCCESS) {
330           IAM_LOGE("Failed to check permission");
331           GlobalUnLock();
332           return ret;
333       }
334       ret = GetCoAuthSchedule(&scheduleInfo);
335       if (ret != RESULT_SUCCESS) {
336           IAM_LOGE("Failed to get schedule info");
337           GlobalUnLock();
338           return ret;
339       }
340       if (!CopyScheduleInfo(&scheduleInfo, &info)) {
341           IAM_LOGE("Failed to copy schedule info");
342           ret = RESULT_BAD_COPY;
343       }
344       GlobalUnLock();
345       return ret;
346   }
347
348   // Start enrollment and generate scheduling information (V1_0 version). The method of V1_0 is called to invoke the method of V1_1 through parameter conversion.
349   int32_t UserAuthInterfaceService::BeginEnrollment(int32_t userId, const std::vector<uint8_t> &authToken,
350       const EnrollParam &param, ScheduleInfo &info)
351   {
352       IAM_LOGI("start");
353       ScheduleInfoV1_1 infoV1_1;
354       int32_t ret = BeginEnrollmentV1_1(userId, authToken, param, infoV1_1);
355       CopyScheduleInfoV1_1ToV1_0(infoV1_1, info);
356       return ret;
357   }
358
359   // Cancel the enrollment operation.
360   int32_t UserAuthInterfaceService::CancelEnrollment(int32_t userId)
361   {
362       IAM_LOGI("start");
363       BreakOffCoauthSchedule(userId);
364       return RESULT_SUCCESS;
365   }
366
367   // Update the enrolled credential information.
368   int32_t UserAuthInterfaceService::UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t>& scheduleResult,
369       uint64_t& credentialId, CredentialInfo& oldInfo)
370   {
371       IAM_LOGI("start");
372       GlobalLock();
373       if (scheduleResult.size() == 0) {
374           IAM_LOGE("enrollToken is invalid");
375           GlobalUnLock();
376           return RESULT_BAD_PARAM;
377       }
378       Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size());
379       if (scheduleResultBuffer == nullptr) {
380           IAM_LOGE("scheduleTokenBuffer is null");
381           GlobalUnLock();
382           return RESULT_NO_MEMORY;
383       }
384       bool isUpdate;
385       int32_t ret = GetIsUpdate(&isUpdate);
386       if (ret != RESULT_SUCCESS) {
387           IAM_LOGE("Failed to get isUpdate");
388           return ret;
389       }
390       if (isUpdate) {
391           CredentialInfoHal oldCredentialHal;
392           ret = UpdateCredentialFunc(scheduleResultBuffer, &credentialId, &oldCredentialHal);
393           oldInfo.authType = static_cast<AuthType>(oldCredentialHal.authType);
394           oldInfo.credentialId = oldCredentialHal.credentialId;
395           oldInfo.templateId = oldCredentialHal.templateId;
396           oldInfo.executorType = static_cast<uint32_t>(oldCredentialHal.authSubType);
397           oldInfo.executorId = 0;
398           oldInfo.index = 0;
399       } else {
400           ret = AddCredentialFunc(scheduleResultBuffer, &credentialId);
401       }
402       DestoryBuffer(scheduleResultBuffer);
403       GlobalUnLock();
404       return ret;
405   }
406   ```
407
4084. 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).
409
410   ```c++
411   // Create an HDI service object.
412   extern "C" IUserAuthInterface *UserAuthInterfaceImplGetInstance(void)
413   {
414       auto userAuthInterfaceService = new (std::nothrow) UserAuthInterfaceService();
415       if (userAuthInterfaceService == nullptr) {
416           IAM_LOGE("userAuthInterfaceService is nullptr");
417           return nullptr;
418       }
419       return userAuthInterfaceService;
420   }
421
422   // Start an authentication to generate the authentication scheme and scheduling information.
423   int32_t UserAuthInterfaceService::BeginAuthenticationV1_1(uint64_t contextId, const AuthSolution& param,
424       std::vector<ScheduleInfoV1_1>& infos)
425   {
426       IAM_LOGI("start");
427       if (param.challenge.size() != sizeof(uint64_t)) {
428           IAM_LOGE("Failed to copy challenge");
429           return RESULT_BAD_PARAM;
430       }
431       GlobalLock();
432       CoAuthSchedule *schedulesGet = nullptr;
433       uint32_t scheduleIdNum = 0;
434       AuthSolutionHal solutionIn;
435       solutionIn.contextId = contextId;
436       solutionIn.userId = param.userId;
437       solutionIn.authType = static_cast<uint32_t>(param.authType);
438       solutionIn.authTrustLevel = param.authTrustLevel;
439       if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), &param.challenge[0],
440           param.challenge.size()) != EOK) {
441           IAM_LOGE("Failed to copy challenge");
442           GlobalUnLock();
443           return RESULT_BAD_COPY;
444       }
445       int32_t ret = GenerateSolutionFunc(solutionIn, &schedulesGet, &scheduleIdNum);
446       if (ret != RESULT_SUCCESS) {
447           IAM_LOGE("Failed to generate solution");
448           GlobalUnLock();
449           return ret;
450       }
451       for (uint32_t i = 0; i < scheduleIdNum; i++) {
452           ScheduleInfoV1_1 temp;
453           if (!CopyScheduleInfo(schedulesGet + i, &temp)) {
454               infos.clear();
455               ret = RESULT_GENERAL_ERROR;
456               break;
457           }
458           infos.push_back(temp);
459       }
460       free(schedulesGet);
461       GlobalUnLock();
462       return ret;
463   }
464
465   // Start user authentication, generate the authentication scheme and scheduling information. The method of V1_0 is called to invoke the method of V1_1 through parameter conversion.
466   int32_t UserAuthInterfaceService::BeginAuthentication(uint64_t contextId, const AuthSolution &param,
467       std::vector<ScheduleInfo> &infos)
468   {
469       IAM_LOGI("start");
470       std::vector<ScheduleInfoV1_1> infosV1_1;
471       int32_t ret = BeginAuthenticationV1_1(contextId, param, infosV1_1);
472       CopyScheduleInfosV1_1ToV1_0(infosV1_1, infos);
473       return ret;
474   }
475
476   // Update the authentication result to evaluate the authentication scheme.
477   int32_t UserAuthInterfaceService::UpdateAuthenticationResult(uint64_t contextId,
478       const std::vector<uint8_t>& scheduleResult, AuthResultInfo& info)
479   {
480       IAM_LOGI("start");
481       GlobalLock();
482       if (scheduleResult.size() == 0) {
483           IAM_LOGE("param is invalid");
484           info.result = RESULT_BAD_PARAM;
485           GlobalUnLock();
486           return RESULT_BAD_PARAM;
487       }
488       Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size());
489       if (scheduleResultBuffer == nullptr) {
490           IAM_LOGE("scheduleTokenBuffer is null");
491           info.result = RESULT_GENERAL_ERROR;
492           GlobalUnLock();
493           return RESULT_NO_MEMORY;
494       }
495       UserAuthTokenHal authTokenHal;
496       info.result = RequestAuthResultFunc(contextId, scheduleResultBuffer, &authTokenHal);
497       if (info.result != RESULT_SUCCESS) {
498           IAM_LOGE("Failed to execute func");
499           DestoryBuffer(scheduleResultBuffer);
500           GlobalUnLock();
501           return info.result;
502       }
503       info.token.resize(sizeof(UserAuthTokenHal));
504       if (memcpy_s(&info.token[0], info.token.size(), &authTokenHal, sizeof(authTokenHal)) != EOK) {
505           IAM_LOGE("Failed to copy authToken");
506           DestoryBuffer(scheduleResultBuffer);
507           GlobalUnLock();
508           return RESULT_BAD_COPY;
509       }
510       DestoryBuffer(scheduleResultBuffer);
511       GlobalUnLock();
512       return RESULT_SUCCESS;
513   }
514
515   // Cancel the authentication.
516   int32_t UserAuthInterfaceService::CancelAuthentication(uint64_t contextId)
517   {
518       IAM_LOGI("start");
519       GlobalLock();
520       uint32_t scheduleIdNum = 0;
521       int32_t ret = CancelContextFunc(contextId, nullptr, &scheduleIdNum);
522       if (ret != RESULT_SUCCESS) {
523           IAM_LOGE("Failed to execute func");
524           GlobalUnLock();
525           return ret;
526       }
527       GlobalUnLock();
528       return RESULT_SUCCESS;
529   }
530   ```
531
532### Verification
533
534Use the [User Authentication APIs](../../application-dev/reference/apis/js-apis-useriam-userauth.md) to develop a JavaScript application and verify the application on the Hi3516D V300 development board. The sample code for verifying and canceling the authentication is as follows:
535
536    ```js
537    // API version 9
538    import userIAM_userAuth from '@ohos.userIAM.userAuth';
539
540    let challenge = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
541    let authType = userIAM_userAuth.UserAuthType.FACE;
542    let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1;
543
544    // Obtain an authentication object.
545    let auth;
546    try {
547        auth = userIAM_userAuth.getAuthInstance(challenge, authType, authTrustLevel);
548        console.log("get auth instance success");
549    } catch (error) {
550        console.log("get auth instance failed" + error);
551    }
552
553    // Subscribe to the authentication result.
554    try {
555        auth.on("result", {
556            callback: (result: userIAM_userAuth.AuthResultInfo) => {
557                console.log("authV9 result " + result.result);
558                console.log("authV9 token " + result.token);
559                console.log("authV9 remainAttempts " + result.remainAttempts);
560                console.log("authV9 lockoutDuration " + result.lockoutDuration);
561            }
562        });
563        console.log("subscribe authentication event success");
564    } catch (error) {
565        console.log("subscribe authentication event failed " + error);
566    }
567
568    // Start user authentication.
569    try {
570        auth.start();
571        console.info("authV9 start auth success");
572    } catch (error) {
573        console.info("authV9 start auth failed, error = " + error);
574    }
575
576    // Cancel the authentication.
577    try {
578        auth.cancel();
579        console.info("Authentication canceled successfully");
580    } catch (error) {
581        console.info("cancel auth failed, error = " + error);
582    }
583
584    // Unsubscribe from the authentication result.
585    try {
586        auth.off("result");
587        console.info("cancel subscribe authentication event success");
588    } catch (error) {
589        console.info("cancel subscribe authentication event failed, error = " + error);
590    }
591    ```
592