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 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 shield 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 99 100### Constraints 101 102The User_auth driver must be implemented in a 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 HdiExecutorRegisterInfo &info, uint64_t &index, std::vector<uint8_t> &publicKey, 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(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. | 125| UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t> & scheduleResult, EnrollResultInfo &info)| Updates the data to complete this enrollment. | 126| CancelEnrollment(int32_t userId) | Cancels an enrollment. | 127| DeleteCredential(int32_t userId, uint64_t credentialId, const std::vector<uint8_t> &authToken, CredentialInfo &info) | Deletes credential information based on the specified **credentialId**. | 128| 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. | 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, int32_t authType, std::vector<CredentialInfo> &infos) | Obtains user credential information by authentication type. | 131| BeginAuthentication(uint64_t contextId, const HdiAuthParam ¶m, std::vector<HdiScheduleInfo> &infos) | Starts an authentication to generate the authentication scheme and scheduling information. | 132| UpdateAuthenticationResult(uint64_t contextId, const std::vector<uint8_t> & scheduleResult, HdiAuthResultInfo &info, HdiEnrolledState &enrolledState)| Updates the authentication result to evaluate the authentication scheme. | 133| CancelAuthentication(uint64_t contextId) | Cancels an authentication. | 134| 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. | 135| UpdateIdentificationResult(uint64_t contextId, const std::vector<uint8_t> &scheduleResult, IdentifyResultInfo &info) | Updates the identification result to evaluate the identification scheme. | 136| CancelIdentification(uint64_t contextId) | Cancels an identification. | 137| GetAuthTrustLevel(int32_t userId, int32_t authType, uint32_t &authTrustLevel) | Obtains the authentication trust level of the specified authentication type. | 138| 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. | 139| GetAllUserInfo(std::vector<UserInfo> &userInfos) | Obtains all user information (excluding **userId**). | 140| GetUserInfo(int32_t userId, uint64_t &secureUid, int32_t &pinSubType, std::vector<EnrolledInfo> &infos) | Obtains user information. | 141| GetAllExtUserInfo(std::vector<ExtUserInfo> &userInfos) | Obtains all user information (including **userId**). | 142| GetEnrolledState(int32_t userId, int32_t authType, HdiEnrolledState &enrolledState) | Obtains enrollment information. | 143| CheckReuseUnlockResult(const ReuseUnlockParam& param, ReuseUnlockInfo& info) | Checks whether the device unlocking result is reused. | 144| SendMessage(uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t>& msg) | Sends messages to the executor. | 145| RegisterMessageCallback(const sptr<IMessageCallback>& messageCallback) | Registers a callback for executor messages.| 146| GetLocalScheduleFromMessage(const std::vector<uint8_t>& remoteDeviceId, const std::vector<uint8_t>& message, HdiScheduleInfo& scheduleInfo) | Obtains scheduling information of the local executor. | 147| 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. | 148 149### How to Develop 150 151The 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: 152 153```undefined 154// drivers/peripheral/user_auth 155├── BUILD.gn # Build script 156├── bundle.json # Component description file 157└── hdi_service # User_auth driver implementation 158 ├── BUILD.gn # Build script 159 ├── module # Implementation of functionalities 160 └── service 161 ├── user_auth_interface_driver.cpp # User_auth driver entry 162 └── user_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list 163``` 164 165The development procedure is as follows: 166 1671. 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). 168 169 ```c++ 170 // Create an IRemoteObject object by using the custom HdfUserAuthInterfaceHost object, which consists of the IoService object and HDI service. 171 struct HdfUserAuthInterfaceHost { 172 struct IDeviceIoService ioService; 173 OHOS::sptr<OHOS::IRemoteObject> stub; 174 }; 175 176 // Enable the IPC service to call the response API. 177 static int32_t UserAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, 178 struct HdfSBuf *reply) 179 { 180 auto *hdfUserAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfUserAuthInterfaceHost, ioService); 181 182 OHOS::MessageParcel *dataParcel = nullptr; 183 OHOS::MessageParcel *replyParcel = nullptr; 184 OHOS::MessageOption option; 185 186 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 187 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); 188 return HDF_ERR_INVALID_PARAM; 189 } 190 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 191 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); 192 return HDF_ERR_INVALID_PARAM; 193 } 194 195 return hdfUserAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 196 } 197 198 // Initialize the HdfUserAuthInterfaceDriver object. 199 int HdfUserAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 200 { 201 HDF_LOGI("HdfUserAuthInterfaceDriverInit enter"); 202 OHOS::UserIAM::Common::Init(); 203 return HDF_SUCCESS; 204 } 205 206 // Bind the service provided by the User_auth driver to the HDF. 207 int HdfUserAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 208 { 209 HDF_LOGI("HdfUserAuthInterfaceDriverBind enter"); 210 211 auto *hdfUserAuthInterfaceHost = new (std::nothrow) HdfUserAuthInterfaceHost; 212 if (hdfUserAuthInterfaceHost == nullptr) { 213 HDF_LOGE("%{public}s: failed to create HdfUserAuthInterfaceHost object", __func__); 214 return HDF_FAILURE; 215 } 216 217 hdfUserAuthInterfaceHost->ioService.Dispatch = UserAuthInterfaceDriverDispatch; 218 hdfUserAuthInterfaceHost->ioService.Open = NULL; 219 hdfUserAuthInterfaceHost->ioService.Release = NULL; 220 221 auto serviceImpl = IUserAuthInterface::Get(true); 222 if (serviceImpl == nullptr) { 223 HDF_LOGE("%{public}s: failed to implement service", __func__); 224 return HDF_FAILURE; 225 } 226 227 hdfUserAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 228 IUserAuthInterface::GetDescriptor()); 229 if (hdfUserAuthInterfaceHost->stub == nullptr) { 230 HDF_LOGE("%{public}s: failed to get stub object", __func__); 231 return HDF_FAILURE; 232 } 233 234 deviceObject->service = &hdfUserAuthInterfaceHost->ioService; 235 return HDF_SUCCESS; 236 } 237 238 // Release resources of the User_auth driver. 239 void HdfUserAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject){ 240 HDF_LOGI("HdfUserAuthInterfaceDriverRelease enter"); 241 auto *hdfUserAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfUserAuthInterfaceHost, ioService); 242 delete hdfUserAuthInterfaceHost; 243 } 244 245 // Register the User_auth driver entry data structure object. 246 struct HdfDriverEntry g_userAuthInterfaceDriverEntry = { 247 .moduleVersion = 1, 248 .moduleName = "user_auth_device_driver", 249 .Bind = HdfUserAuthInterfaceDriverBind, 250 .Init = HdfUserAuthInterfaceDriverInit, 251 .Release = HdfUserAuthInterfaceDriverRelease, 252 }; 253 254 // 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. 255 #ifndef __cplusplus 256 extern "C" { 257 #endif 258 HDF_INIT(g_userAuthInterfaceDriverEntry); 259 #ifndef __cplusplus 260 } 261 #endif 262 ``` 263 2642. 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). 265 266 ```c++ 267 // Add an executor. 268 int32_t UserAuthInterfaceService::AddExecutor(const HdiExecutorRegisterInfo &info, uint64_t &index, 269 std::vector<uint8_t> &publicKey, std::vector<uint64_t> &templateIds) 270 { 271 GlobalLock(); 272 ExecutorInfoHal executorInfoHal; 273 CopyExecutorInfo(info, executorInfoHal); 274 int32_t ret = RegisterExecutor(&executorInfoHal, &index); 275 GlobalUnLock(); 276 return ret; 277 } 278 279 // Delete the executor. 280 int32_t UserAuthInterfaceService::DeleteExecutor(uint64_t index) 281 { 282 return UnRegisterExecutor(index); 283 } 284 ``` 285 2863. 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). 287 288 ```c++ 289 // Open a session for authentication credential management. 290 int32_t UserAuthInterfaceService::OpenSession(int32_t userId, std::vector<uint8_t>& challenge) 291 { 292 GlobalLock(); 293 uint64_t challengeU64 = 0; 294 int32_t ret = OpenEditSession(userId, &challengeU64); 295 challenge.resize(sizeof(uint64_t)); 296 if (memcpy_s(&challenge[0], challenge.size(), &challengeU64, sizeof(uint64_t)) != EOK) { 297 IAM_LOGE("failed to copy challengeU64"); 298 return RESULT_BAD_COPY; 299 } 300 GlobalUnLock(); 301 return ret; 302 } 303 304 // Close the session for authentication credential management. 305 int32_t UserAuthInterfaceService::CloseSession(int32_t userId) 306 { 307 GlobalLock(); 308 int32_t ret = CloseEditSession(); 309 GlobalUnLock(); 310 return ret; 311 } 312 313 // Start enrollment to generate enrollment and scheduling information. 314 int32_t UserAuthInterfaceService::BeginEnrollment( 315 const std::vector<uint8_t> &authToken, const HdiEnrollParam ¶m, HdiScheduleInfo &info) 316 { 317 IAM_LOGI("start"); 318 GlobalLock(); 319 if (authToken.size() != sizeof(UserAuthTokenHal) && param.authType != PIN) { 320 IAM_LOGE("authToken len is invalid"); 321 GlobalUnLock(); 322 return RESULT_BAD_PARAM; 323 } 324 PermissionCheckParam checkParam; 325 if (authToken.size() == sizeof(UserAuthTokenHal) && 326 memcpy_s(checkParam.token, AUTH_TOKEN_LEN, &authToken[0], authToken.size()) != EOK) { 327 GlobalUnLock(); 328 return RESULT_BAD_COPY; 329 } 330 checkParam.authType = param.authType; 331 checkParam.userId = userId; 332 checkParam.authSubType = (uint64_t)param.executorType; 333 CoAuthSchedule scheduleInfo; 334 int32_t ret = CheckEnrollPermission(checkParam, &scheduleInfo.scheduleId); 335 if (ret != RESULT_SUCCESS) { 336 IAM_LOGE("Failed to check permission"); 337 GlobalUnLock(); 338 return ret; 339 } 340 ret = GetCoAuthSchedule(&scheduleInfo); 341 if (ret != RESULT_SUCCESS) { 342 IAM_LOGE("Failed to get schedule info"); 343 GlobalUnLock(); 344 return ret; 345 } 346 if (!CopyScheduleInfo(&scheduleInfo, &info)) { 347 IAM_LOGE("Failed to copy schedule info"); 348 ret = RESULT_BAD_COPY; 349 } 350 GlobalUnLock(); 351 return ret; 352 } 353 354 // Cancel the enrollment. 355 int32_t UserAuthInterfaceService::CancelEnrollment(int32_t userId) 356 { 357 IAM_LOGI("start"); 358 BreakOffCoauthSchedule(userId); 359 return RESULT_SUCCESS; 360 } 361 362 // Update the enrolled credential information. 363 int32_t UserAuthInterfaceService::UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t> &scheduleResult, EnrollResultInfo &info) 364 { 365 IAM_LOGI("start"); 366 GlobalLock(); 367 if (scheduleResult.size() == 0) { 368 IAM_LOGE("enrollToken is invalid"); 369 GlobalUnLock(); 370 return RESULT_BAD_PARAM; 371 } 372 Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 373 if (scheduleResultBuffer == nullptr) { 374 IAM_LOGE("scheduleTokenBuffer is null"); 375 GlobalUnLock(); 376 return RESULT_NO_MEMORY; 377 } 378 bool isUpdate; 379 int32_t ret = GetIsUpdate(&isUpdate); 380 if (ret != RESULT_SUCCESS) { 381 IAM_LOGE("Failed to get isUpdate"); 382 return ret; 383 } 384 if (isUpdate) { 385 CredentialInfoHal oldCredentialHal; 386 ret = UpdateCredentialFunc(scheduleResultBuffer, &credentialId, &oldCredentialHal); 387 oldInfo.authType = static_cast<AuthType>(oldCredentialHal.authType); 388 oldInfo.credentialId = oldCredentialHal.credentialId; 389 oldInfo.templateId = oldCredentialHal.templateId; 390 oldInfo.executorType = static_cast<uint32_t>(oldCredentialHal.authSubType); 391 oldInfo.executorId = 0; 392 oldInfo.index = 0; 393 } else { 394 ret = AddCredentialFunc(scheduleResultBuffer, &credentialId); 395 } 396 DestoryBuffer(scheduleResultBuffer); 397 GlobalUnLock(); 398 return ret; 399 } 400 ``` 401 4024. 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). 403 404 ```c++ 405 // Create an HDI service object. 406 extern "C" IUserAuthInterface *UserAuthInterfaceImplGetInstance(void) 407 { 408 auto userAuthInterfaceService = new (std::nothrow) UserAuthInterfaceService(); 409 if (userAuthInterfaceService == nullptr) { 410 IAM_LOGE("userAuthInterfaceService is nullptr"); 411 return nullptr; 412 } 413 return userAuthInterfaceService; 414 } 415 416 // Start an authentication to generate the authentication scheme and scheduling information. 417 int32_t UserAuthInterfaceService::BeginAuthentication(uint64_t contextId, const HdiAuthParam ¶m, 418 std::vector<HdiScheduleInfo> &infos) 419 { 420 IAM_LOGI("start"); 421 if (param.challenge.size() != sizeof(uint64_t)) { 422 IAM_LOGE("Failed to copy challenge"); 423 return RESULT_BAD_PARAM; 424 } 425 GlobalLock(); 426 CoAuthSchedule *schedulesGet = nullptr; 427 uint32_t scheduleIdNum = 0; 428 AuthSolutionHal solutionIn; 429 solutionIn.contextId = contextId; 430 solutionIn.userId = param.userId; 431 solutionIn.authType = static_cast<uint32_t>(param.authType); 432 solutionIn.authTrustLevel = param.authTrustLevel; 433 if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), ¶m.challenge[0], 434 param.challenge.size()) != EOK) { 435 IAM_LOGE("Failed to copy challenge"); 436 GlobalUnLock(); 437 return RESULT_BAD_COPY; 438 } 439 int32_t ret = GenerateSolutionFunc(solutionIn, &schedulesGet, &scheduleIdNum); 440 if (ret != RESULT_SUCCESS) { 441 IAM_LOGE("Failed to generate solution"); 442 GlobalUnLock(); 443 return ret; 444 } 445 for (uint32_t i = 0; i < scheduleIdNum; i++) { 446 ScheduleInfoV1_1 temp; 447 if (!CopyScheduleInfo(schedulesGet + i, &temp)) { 448 infos.clear(); 449 ret = RESULT_GENERAL_ERROR; 450 break; 451 } 452 infos.push_back(temp); 453 } 454 free(schedulesGet); 455 GlobalUnLock(); 456 return ret; 457 } 458 459 // Update the authentication result to evaluate the authentication scheme. 460 int32_t UserAuthInterfaceService::UpdateAuthenticationResult(uint64_t contextId, 461 const std::vector<uint8_t> &scheduleResult, HdiAuthResultInfo &info, HdiEnrolledState &enrolledState) 462 { 463 IAM_LOGI("start"); 464 GlobalLock(); 465 if (scheduleResult.size() == 0) { 466 IAM_LOGE("param is invalid"); 467 info.result = RESULT_BAD_PARAM; 468 GlobalUnLock(); 469 return RESULT_BAD_PARAM; 470 } 471 Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 472 if (scheduleResultBuffer == nullptr) { 473 IAM_LOGE("scheduleTokenBuffer is null"); 474 info.result = RESULT_GENERAL_ERROR; 475 GlobalUnLock(); 476 return RESULT_NO_MEMORY; 477 } 478 UserAuthTokenHal authTokenHal; 479 info.result = RequestAuthResultFunc(contextId, scheduleResultBuffer, &authTokenHal); 480 if (info.result != RESULT_SUCCESS) { 481 IAM_LOGE("Failed to execute func"); 482 DestoryBuffer(scheduleResultBuffer); 483 GlobalUnLock(); 484 return info.result; 485 } 486 info.token.resize(sizeof(UserAuthTokenHal)); 487 if (memcpy_s(&info.token[0], info.token.size(), &authTokenHal, sizeof(authTokenHal)) != EOK) { 488 IAM_LOGE("Failed to copy authToken"); 489 DestoryBuffer(scheduleResultBuffer); 490 GlobalUnLock(); 491 return RESULT_BAD_COPY; 492 } 493 DestoryBuffer(scheduleResultBuffer); 494 GlobalUnLock(); 495 return RESULT_SUCCESS; 496 } 497 498 // Cancel the authentication. 499 int32_t UserAuthInterfaceService::CancelAuthentication(uint64_t contextId) 500 { 501 IAM_LOGI("start"); 502 GlobalLock(); 503 uint32_t scheduleIdNum = 0; 504 int32_t ret = CancelContextFunc(contextId, nullptr, &scheduleIdNum); 505 if (ret != RESULT_SUCCESS) { 506 IAM_LOGE("Failed to execute func"); 507 GlobalUnLock(); 508 return ret; 509 } 510 GlobalUnLock(); 511 return RESULT_SUCCESS; 512 } 513 ``` 514 515### Verification 516 517Use 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. 518 5191. Initiate a request for user authentication and obtain the authentication result. 520 521```ts 522 // API version 10 523 import type {BusinessError} from '@ohos.base'; 524 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 525 526 // Set authentication parameters. 527 const authParam: userIAM_userAuth.AuthParam = { 528 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 529 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 530 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 531 }; 532 // Set the authentication page. 533 const widgetParam: userIAM_userAuth.WidgetParam = { 534 title: 'Verify identity', 535 }; 536 try { 537 // Obtain an authentication object. 538 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 539 console.info('get userAuth instance success'); 540 // Subscribe to the authentication result. 541 userAuthInstance.on('result', { 542 onResult(result) { 543 console.info(`userAuthInstance callback result: ${JSON.stringify(result)}`); 544 // Unsubscribe from the authentication result if required. 545 userAuthInstance.off('result'); 546 } 547 }); 548 console.info('auth on success'); 549 userAuthInstance.start(); 550 console.info('auth start success'); 551 } catch (error) { 552 const err: BusinessError = error as BusinessError; 553 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 554 } 555``` 556 5572. Cancel an authentication. 558 559```ts 560 // API version 10 561 import type {BusinessError} from '@ohos.base'; 562 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 563 564 const authParam: userIAM_userAuth.AuthParam = { 565 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 566 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 567 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 568 }; 569 const widgetParam: userIAM_userAuth.WidgetParam = { 570 title: 'Verify identity', 571 }; 572 try { 573 // Obtain an authentication object. 574 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 575 console.info('get userAuth instance success'); 576 // Start user authentication. 577 userAuthInstance.start(); 578 console.info('auth start success'); 579 // Cancel the authentication. 580 userAuthInstance.cancel(); 581 console.info('auth cancel success'); 582 } catch (error) { 583 const err: BusinessError = error as BusinessError; 584 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 585 } 586``` 587