• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Facial Authentication
2
3## Overview
4
5### Function
6
7Facial authentication provides user authentication capabilities in identity authentication scenarios, such as device unlocking, payment, and app logins. It uses biometric recognition technologies to identify individuals based on facial characteristics. A camera is used to collect images or video streams that contain human faces, and automatically detect, track, and recognize human faces. Facial authentication is also called facial recognition. The figure below shows the architecture of facial authentication.
8
9The face authentication (Face_auth) driver is developed based on the Hardware Driver Foundation (HDF). It shields hardware differences and provides stable facial authentication capabilities for the user authentication framework (User_auth) and Face_auth service. The facial authentication capabilities include obtaining facial recognition executor list, executor information, and template information by template ID, comparing face image template information of the executor and that of User_auth, enrolling or deleting face images, and performing facial authentication.
10
11**Figure 1** Facial authentication architecture
12
13![image](figures/face_auth_architecture.png "Facial authentication architecture")
14
15### Basic Concepts
16
17The identity authentication consists of User_auth and basic authentication services (including PIN authentication and facial authentication). It supports basic functions such as setting and deleting user credentials and performing authentication. The system supports user identity authentication and data collection, processing, storage, and comparison.
18- Executor
19
20  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.
21
22- Executor security level
23
24  Security level of the runtime environment when an executor provides capabilities.
25
26- Executor role
27
28  - 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.
29
30  - Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication.
31
32  - Authenticator: only processes data, obtains the stored credential template, and compares it with the authentication information generated.
33
34- Executor type
35
36  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.
37
38- User_auth public key & executor public key
39
40  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.
41
42    The executor uses the User_auth public key to verify scheduling instructions.
43
44    User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor.
45
46- Authentication credential template
47
48  Authentication credentials are generated and stored by the authentication service when users set authentication credentials. 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.
49
50- Data verification by the executor
51
52  User_auth manages the mappings between user identities and credential IDs in a unified manner. When connecting to User_auth, the executor obtains the template ID list from User_auth and updates its template ID list based on the template ID list obtained.
53
54- HAPs
55
56  In a broad sense, OpenHarmony Ability Packages (HAPs) are application packages that can be installed on OpenHarmony. In this document, the HAPs only refer to the upper-layer applications of the Face_auth driver.
57
58- IDL interface
59
60  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 Face_auth service and driver. For details, see [IDL](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md).
61
62- IPC
63
64  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).
65
66- HDI
67
68  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).
69
70### Working Principles
71
72The Face_auth driver provides basic facial authentication capabilities for the User_auth and Face_auth service to ensure successful facial authentication.
73You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use.
74
75**Figure 2** Face_auth service and Face_auth driver interaction
76
77![image](figures/face_auth_service_and_driver_interaction.png "Face_auth service and Face_auth driver interaction")
78
79### Constraints
80
81- To implement facial authentication, the device must have a camera and the face image must be greater than 100 x 100 pixels.
82- A Trusted Execution Environment (TEE) must be available, and facial feature information must be encrypted and stored in a TEE.
83- The face matching accuracy varies with people with similar looks and children whose facial features keep changing. If you are concerned about this, consider using other authentication modes.
84
85## Development Guidelines
86
87### When to Use
88
89The Face_auth driver provides basic facial authentication capabilities for the User_auth and Face_auth service to ensure successful facial authentication.
90
91### Available APIs
92
93The 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/face_auth/**.
94
95**Table 1** describes the HDI APIs for face credential enrollment, authentication, recognition, and deletion. **Table 2** describes the callbacks used to return the executor operation result to the framework or return the authentication tip information to upper-layer applications.
96
97**Table 1** Available APIs
98
99| API      | Description        |
100| ----------------------------------- | ---------------------------------- |
101| GetExecutorList(std::vector\<sptr\<V1_0::IExecutor>>& executorList)  | Obtains the executor list (version V1_0).|
102| GetExecutorListV1_1(std::vector\<sptr\<V1_1::IExecutor>>& executorList)      | Obtains the executor list (version V1_1).                        |
103| GetExecutorInfo(ExecutorInfo& info)      | Obtains the executor information, including the executor type, executor role, authentication type, security level, and executor public key.|
104| GetTemplateInfo(uint64_t templateId, TemplateInfo& info)     | Obtains information about a face image template based on the specified template ID.       |
105| OnRegisterFinish(const std::vector\<uint64_t>& templateIdList,<br>        const std::vector\<uint8_t>& frameworkPublicKey, const std::vector\<uint8_t>& extraInfo) | Obtains the public key and template ID list from User_auth after the executor is registered successfully.|
106| Enroll(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br>        const sptr\<IExecutorCallback>& callbackObj) | Enrolls a face image template.            |
107| Authenticate(uint64_t scheduleId, const std::vector\<uint64_t>& templateIdList,<br>        const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | Performs facial authentication.        |
108| Identify(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br>        const sptr\<IExecutorCallback>& callbackObj) | Performs facial identification.                                              |
109| Delete(const std::vector\<uint64_t>& templateIdList)          | Deletes a face image template. |
110| Cancel(uint64_t scheduleId)                                  | Cancels a face enrollment, authentication, or identification operation based on the **scheduleId**. |
111| SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br>        const sptr\<IExecutorCallback>& callbackObj) | Sends commands to the Face_auth service.             |
112| SetBufferProducer(const sptr\<BufferProducerSequenceable> &bufferProducer) | Sets the preview stream buffer.|
113| GetProperty(const std::vector\<uint64_t>& templateIdList,<br>const std::vector\<GetPropertyType>& propertyTypes, Property& property) | Obtains executor property information.|
114| SetCachedTemplates(const std::vector\<uint64_t> &templateIdList) | Sets a list of templates to be cached.|
115| RegisterSaCommandCallback(const sptr\<ISaCommandCallback> &callbackObj) | Registers a callback to be invoked when an SA command is executed.|
116
117**Table 2** Callbacks
118
119| API                                                      | Description                |
120| ------------------------------------------------------------ | ------------------------ |
121| IExecutorCallback::OnResult(int32_t code, const std::vector\<uint8_t>& extraInfo) | Called to return the operation result.    |
122| IExecutorCallback::OnTip(int32_t code, const std::vector\<uint8_t>& extraInfo) | Called to return the interaction information about the operation process.|
123| ISaCommandCallback::OnSaCommands(const std::vector\<SaCommand>& commands) | Called to send the command list.|
124
125### How to Develop
126
127The following uses the Hi3516D V300 development board as an example to demonstrate how to develop the Face_auth driver. <br/>The directory structure is as follows:
128
129```undefined
130// drivers/peripheral/face_auth
131├── BUILD.gn      # Build script
132├── bundle.json   # Component description file
133└── hdi_service   # Face_auth driver implementation
134    ├── BUILD.gn  # Build script
135    ├── include   # Header files
136    └── src       # Source files
137        ├── executor_impl.cpp                # Implementation of authentication and enrollment APIs
138        ├── face_auth_interface_driver.cpp   # Face_auth driver entry
139        └── face_auth_interface_service.cpp  # Implementation of the APIs for obtaining the executor list
140```
141
142The development procedure is as follows:
143
1441. Develop the Face_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [face_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_driver.cpp).
145
146   ```c++
147   // Create an IRemoteObject object by using the custom HdfFaceAuthInterfaceHost object, which consists of the IoService object and HDI service.
148   struct HdfFaceAuthInterfaceHost {
149       struct IDeviceIoService ioService;
150       OHOS::sptr<OHOS::IRemoteObject> stub;
151   };
152
153   // Enable the IPC service to call the response API.
154   static int32_t FaceAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
155       struct HdfSBuf *reply)
156   {
157       IAM_LOGI("start");
158       auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(client->device->service,
159           struct HdfFaceAuthInterfaceHost, ioService);
160
161       OHOS::MessageParcel *dataParcel = nullptr;
162       OHOS::MessageParcel *replyParcel = nullptr;
163       OHOS::MessageOption option;
164
165       if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
166           IAM_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
167           return HDF_ERR_INVALID_PARAM;
168       }
169       if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
170           IAM_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
171           return HDF_ERR_INVALID_PARAM;
172       }
173
174       return hdfFaceAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
175   }
176
177   // Initialize the HdfFaceAuthInterfaceDriver object.
178   int HdfFaceAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
179   {
180       IAM_LOGI("start");
181       if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_USERAUTH)) {
182           IAM_LOGE("set face auth hdf class failed");
183           return HDF_FAILURE;
184       }
185       return HDF_SUCCESS;
186   }
187
188   // Bind the service provided by the Face_auth driver to the HDF.
189   int HdfFaceAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
190   {
191       IAM_LOGI("start");
192       auto *hdfFaceAuthInterfaceHost = new (std::nothrow) HdfFaceAuthInterfaceHost;
193       if (hdfFaceAuthInterfaceHost == nullptr) {
194           IAM_LOGE("%{public}s: failed to create HdfFaceAuthInterfaceHost object", __func__);
195           return HDF_FAILURE;
196       }
197
198       hdfFaceAuthInterfaceHost->ioService.Dispatch = FaceAuthInterfaceDriverDispatch;
199       hdfFaceAuthInterfaceHost->ioService.Open = NULL;
200       hdfFaceAuthInterfaceHost->ioService.Release = NULL;
201
202       auto serviceImpl = IFaceAuthInterface::Get(true);
203       if (serviceImpl == nullptr) {
204           IAM_LOGE("%{public}s: failed to implement service", __func__);
205           return HDF_FAILURE;
206       }
207
208       hdfFaceAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
209           IFaceAuthInterface::GetDescriptor());
210       if (hdfFaceAuthInterfaceHost->stub == nullptr) {
211           IAM_LOGE("%{public}s: Failed to get stub object", __func__);
212           return HDF_FAILURE;
213       }
214
215       deviceObject->service = &hdfFaceAuthInterfaceHost->ioService;
216       IAM_LOGI("success");
217       return HDF_SUCCESS;
218   }
219
220   // Release resources of the Face_auth driver.
221   void HdfFaceAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
222   {
223       IAM_LOGI("start");
224       auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(deviceObject->service,
225           struct HdfFaceAuthInterfaceHost, ioService);
226       delete hdfFaceAuthInterfaceHost;
227       IAM_LOGI("success");
228   }
229
230   // Register the entry data structure object of the Face_auth driver.
231   struct HdfDriverEntry g_faceAuthInterfaceDriverEntry = {
232       .moduleVersion = 1,
233       .moduleName = "faceauth_interface_service",
234       .Bind = HdfFaceAuthInterfaceDriverBind,
235       .Init = HdfFaceAuthInterfaceDriverInit,
236       .Release = HdfFaceAuthInterfaceDriverRelease,
237   };
238
239   // 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.
240   HDF_INIT(g_faceAuthInterfaceDriverEntry);
241   ```
242
2432. Implement the APIs for obtaining the executor list. For details about the code, see [face_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_service.cpp).
244
245   ```c++
246   // Executor implementation class
247   class ExecutorImpl : public V1_1::IExecutor {
248   public:
249       ExecutorImpl(struct ExecutorInfo executorInfo);
250       virtual ~ExecutorImpl() {}
251
252   private:
253       struct ExecutorInfo executorInfo_; // Executor information
254   };
255
256   static constexpr uint16_t SENSOR_ID = 123; // Executor sensor ID
257   static constexpr uint32_t EXECUTOR_TYPE = 123; // Executor type
258   static constexpr size_t PUBLIC_KEY_LEN = 32; //32-byte public key of the executor
259
260   // Create an HDI service object.
261   extern "C" IFaceAuthInterface *FaceAuthInterfaceImplGetInstance(void)
262   {
263       auto faceAuthInterfaceService = new (std::nothrow) FaceAuthInterfaceService();
264       if (faceAuthInterfaceService == nullptr) {
265           IAM_LOGE("faceAuthInterfaceService is nullptr");
266           return nullptr;
267       }
268       return faceAuthInterfaceService;
269   }
270
271   // Obtain the executor list and create an executor.
272   int32_t GetExecutorListV1_1(std::vector<sptr<V1_1::IExecutor>>& executorList)
273   {
274       IAM_LOGI("interface mock start");
275       executorList.clear();
276       struct ExecutorInfo executorInfoExample = {
277           .sensorId = SENSOR_ID,
278           .executorType = EXECUTOR_TYPE,
279           .executorRole = ExecutorRole::ALL_IN_ONE,
280           .authType = AuthType::FACE,
281           .esl = ExecutorSecureLevel::ESL0, // Executor security level, which ranges from ESL0 to ESL3 (highest).
282           .publicKey = std::vector<uint8_t>(PUBLIC_KEY_LEN, 0), // 32-byte public key, using the Ed25519 algorithm.
283           .extraInfo = {},
284       };
285       auto executor = new (std::nothrow) ExecutorImpl(executorInfoExample);
286       if (executor == nullptr) {
287           IAM_LOGE("executor is nullptr");
288           return HDF_FAILURE;
289       }
290       executorList.push_back(sptr<V1_1::IExecutor>(executor));
291       IAM_LOGI("interface mock success");
292       return HDF_SUCCESS;
293   }
294
295   // Obtain the executor list. The method of V1_0 is called to invoke the method of V1_1 through parameter conversion.
296   int32_t GetExecutorList(std::vector<sptr<V1_0::IExecutor>> &executorList)
297   {
298       std::vector<sptr<V1_1::IExecutor>> executorListV1_1;
299       int32_t result = GetExecutorListV1_1(executorListV1_1);
300       for (auto &executor : executorListV1_1) {
301           executorList.push_back(executor);
302       }
303       return result;
304   }
305   ```
306
3073. Implement each function of the executor. For details about the code, see [executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/executor_impl.cpp).
308
309   ```c++
310   // Obtain the executor information.
311   int32_t GetExecutorInfo(ExecutorInfo& info)
312   {
313       IAM_LOGI("interface mock start");
314       info = executorInfo_;
315       IAM_LOGI("Executor information got successfully");
316       return HDF_SUCCESS;
317   }
318
319   // Obtain template information based on templateId.
320   int32_t GetTemplateInfo(uint64_t templateId, TemplateInfo& info)
321   {
322       IAM_LOGI("interface mock start");
323       static_cast<void>(templateId);
324       info = {0};
325       IAM_LOGI("Template information got successfully");
326       return HDF_SUCCESS;
327   }
328
329   // After the executor is successfully registered, obtain the public key and template ID list from User_auth and save the public key. The executor compares its template ID list with the template ID list obtained and updates its template ID list.
330   int32_t OnRegisterFinish(const std::vector<uint64_t>& templateIdList,
331       const std::vector<uint8_t>& frameworkPublicKey, const std::vector<uint8_t>& extraInfo)
332   {
333       IAM_LOGI("interface mock start");
334       static_cast<void>(templateIdList);
335       static_cast<void>(extraInfo);
336       static_cast<void>(frameworkPublicKey);
337       IAM_LOGI("registration finished");
338       return HDF_SUCCESS;
339   }
340
341   // Enroll a face image.
342   int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo,
343       const sptr<IExecutorCallback>& callbackObj)
344   {
345       IAM_LOGI("interface mock start");
346       static_cast<void>(scheduleId);
347       static_cast<void>(extraInfo);
348       IAM_LOGI("enroll, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT);
349       int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {});
350       if (ret != ResultCode::SUCCESS) {
351           IAM_LOGE("callback result is %{public}d", ret);
352           return HDF_FAILURE;
353       }
354       return HDF_SUCCESS;
355   }
356
357   // Start facial authentication.
358   int32_t Authenticate(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList,
359       const std::vector<uint8_t>& extraInfo, const sptr<IExecutorCallback>& callbackObj)
360   {
361       IAM_LOGI("interface mock start");
362       static_cast<void>(scheduleId);
363       static_cast<void>(templateIdList);
364       static_cast<void>(extraInfo);
365       IAM_LOGI("authenticate, result is %{public}d", ResultCode::NOT_ENROLLED);
366       int32_t ret = callbackObj->OnResult(ResultCode::NOT_ENROLLED, {});
367       if (ret != ResultCode::SUCCESS) {
368           IAM_LOGE("callback result is %{public}d", ret);
369           return HDF_FAILURE;
370       }
371       return HDF_SUCCESS;
372   }
373
374   // Perform facial recognition.
375   int32_t Identify(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo,
376       const sptr<IExecutorCallback>& callbackObj)
377   {
378       IAM_LOGI("interface mock start");
379       static_cast<void>(scheduleId);
380       static_cast<void>(extraInfo);
381       IAM_LOGI("identify, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT);
382       int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {});
383       if (ret != ResultCode::SUCCESS) {
384           IAM_LOGE("callback result is %{public}d", ret);
385           return HDF_FAILURE;
386       }
387       return HDF_SUCCESS;
388   }
389
390   // Delete the face image template.
391   int32_t Delete(const std::vector<uint64_t>& templateIdList)
392   {
393       IAM_LOGI("interface mock start");
394       static_cast<void>(templateIdList);
395       IAM_LOGI("delete success");
396       return HDF_SUCCESS;
397   }
398
399   // Cancel the operation based on the specified scheduleId.
400   int32_t Cancel(uint64_t scheduleId)
401   {
402       IAM_LOGI("interface mock start");
403       static_cast<void>(scheduleId);
404       IAM_LOGI("cancel success");
405       return HDF_SUCCESS;
406   }
407
408   // Send template locking or unlocking command from the Face_auth service to the Face_auth driver.
409   int32_t SendCommand(int32_t commandId, const std::vector<uint8_t>& extraInfo,
410       const sptr<IExecutorCallback>& callbackObj)
411   {
412       IAM_LOGI("interface mock start");
413       static_cast<void>(extraInfo);
414       int32_t ret;
415       switch (commandId) {
416           case LOCK_TEMPLATE:
417               IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS);
418               ret = callbackObj->OnResult(ResultCode::SUCCESS, {});
419               if (ret != ResultCode::SUCCESS) {
420                   IAM_LOGE("callback result is %{public}d", ret);
421                   return HDF_FAILURE;
422               }
423               break;
424           case UNLOCK_TEMPLATE:
425               IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS);
426               ret = callbackObj->OnResult(ResultCode::SUCCESS, {});
427               if (ret != ResultCode::SUCCESS) {
428                   IAM_LOGE("callback result is %{public}d", ret);
429                   return HDF_FAILURE;
430               }
431               break;
432           default:
433               IAM_LOGD("not support CommandId : %{public}d", commandId);
434               ret = callbackObj->OnResult(ResultCode::GENERAL_ERROR, {});
435               if (ret != ResultCode::SUCCESS) {
436                   IAM_LOGE("callback result is %{public}d", ret);
437                   return HDF_FAILURE;
438               }
439       }
440       return HDF_SUCCESS;
441   }
442
443   // Set the preview stream buffer.
444   int32_t ExecutorImpl::SetBufferProducer(const sptr<BufferProducerSequenceable> &bufferProducer)
445   {
446       IAM_LOGI("interface mock start set buffer producer %{public}s",
447           UserIam::Common::GetPointerNullStateString(bufferProducer.GetRefPtr()).c_str());
448       return HDF_SUCCESS;
449   }
450
451   // Obtaining executor properties.
452   int32_t ExecutorImpl::GetProperty(
453       const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property)
454   {
455       IAM_LOGI("interface mock start");
456       property = {};
457       IAM_LOGI("get property success");
458       return HDF_SUCCESS;
459   }
460
461   // Set a list of templates to be cached.
462   int32_t ExecutorImpl::SetCachedTemplates(const std::vector<uint64_t> &templateIdList)
463   {
464       IAM_LOGI("interface mock start");
465       IAM_LOGI("set cached templates success");
466       return HDF_SUCCESS;
467   }
468
469   // Register the callback to be invoked when the SA command is executed.
470   int32_t ExecutorImpl::RegisterSaCommandCallback(const sptr<ISaCommandCallback> &callbackObj)
471   {
472       IAM_LOGI("interface mock start");
473       IAM_LOGI("register sa command callback success");
474       return HDF_SUCCESS;
475   }
476   ```
477
4784. Modify **serviceName2Config** in the **face_auth_service.cpp** file if you need to add a driver or modify driver information.
479
480   ```c++
481   // base/user_iam/face_auth/services/src/face_auth_service.cpp
482   void FaceAuthService::StartDriverManager()
483   {
484       IAM_LOGI("start");
485       // Service name and ID of the driver to add or modify. The driver service name and ID must be globally unique.
486       const std::map<std::string, UserAuth::ServiceConfig> serviceName2Config = {
487           {"face_auth_interface_service", {1, std::make_shared<FaceAuthDriverHdi>()}},
488       };
489       UserIAM::UserAuth::IDriverManager::GetInstance().Start(serviceName2Config);
490   }
491   ```
492
493### Verification
494
495Use 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:
496
497    ```js
498    // API version 9
499    import userIAM_userAuth from '@ohos.userIAM.userAuth';
500
501    let challenge = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]);
502    let authType = userIAM_userAuth.UserAuthType.FACE;
503    let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1;
504
505    // Obtain an authentication object.
506    let auth;
507    try {
508        auth = userIAM_userAuth.getAuthInstance(challenge, authType, authTrustLevel);
509        console.log("get auth instance success");
510    } catch (error) {
511        console.log("get auth instance failed" + error);
512    }
513
514    // Subscribe to the authentication result.
515    try {
516        auth.on("result", {
517            callback: (result: userIAM_userAuth.AuthResultInfo) => {
518                console.log("authV9 result " + result.result);
519                console.log("authV9 token " + result.token);
520                console.log("authV9 remainAttempts " + result.remainAttempts);
521                console.log("authV9 lockoutDuration " + result.lockoutDuration);
522            }
523        });
524        console.log("subscribe authentication event success");
525    } catch (error) {
526        console.log("subscribe authentication event failed " + error);
527    }
528
529    // Start user authentication.
530    try {
531        auth.start();
532        console.info("authV9 start auth success");
533    } catch (error) {
534        console.info("authV9 start auth failed, error = " + error);
535    }
536
537    // Cancel the authentication.
538    try {
539        auth.cancel();
540        console.info("Authentication canceled successfully");
541    } catch (error) {
542        console.info("cancel auth failed, error = " + error);
543    }
544
545    // Unsubscribe from the authentication result.
546    try {
547        auth.off("result");
548        console.info("cancel subscribe authentication event success");
549    } catch (error) {
550        console.info("cancel subscribe authentication event failed, error = " + error);
551    }
552    ```
553