1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "user_auth_instance_v10.h"
17
18 #include <algorithm>
19 #include <string>
20
21 #include "iam_logger.h"
22 #include "iam_ptr.h"
23
24 #include "user_auth_client_impl.h"
25
26 #define LOG_LABEL Common::LABEL_USER_AUTH_NAPI
27
28 namespace OHOS {
29 namespace UserIam {
30 namespace UserAuth {
31 const std::string AUTH_EVENT_RESULT = "result";
32 const std::string AUTH_PARAM_CHALLENGE = "challenge";
33 const std::string AUTH_PARAM_AUTHTYPE = "authType";
34 const std::string AUTH_PARAM_AUTHTRUSTLEVEL = "authTrustLevel";
35 const std::string WIDGET_PARAM_TITLE = "title";
36 const std::string WIDGET_PARAM_NAVIBTNTEXT = "navigationButtonText";
37 const std::string WIDGET_PARAM_WINDOWMODE = "windowMode";
38 const std::string NOTICETYPE = "noticeType";
39
40 namespace WidgetType {
41 constexpr int32_t TITLE_MAX = 500;
42 constexpr int32_t BUTTON_MAX = 60;
43 }
44
UserAuthInstanceV10(napi_env env)45 UserAuthInstanceV10::UserAuthInstanceV10(napi_env env) : callback_(Common::MakeShared<UserAuthCallbackV10>(env))
46 {
47 if (callback_ == nullptr) {
48 IAM_LOGE("get null callback");
49 }
50 authParam_.authTrustLevel = AuthTrustLevel::ATL1;
51 widgetParam_.navigationButtonText = "";
52 widgetParam_.title = "";
53 widgetParam_.windowMode = WindowModeType::UNKNOWN_WINDOW_MODE;
54 }
55
InitChallenge(napi_env env,napi_value value)56 UserAuthResultCode UserAuthInstanceV10::InitChallenge(napi_env env, napi_value value)
57 {
58 authParam_.challenge.clear();
59 napi_status ret = UserAuthNapiHelper::CheckNapiType(env, value, napi_null);
60 if (ret == napi_ok) {
61 IAM_LOGI("challenge is null");
62 return UserAuthResultCode::OHOS_INVALID_PARAM;
63 }
64 ret = UserAuthNapiHelper::GetUint8ArrayValue(env, value, MAX_CHALLENG_LEN, authParam_.challenge);
65 if (ret != napi_ok) {
66 IAM_LOGE("GetUint8ArrayValue fail:%{public}d", ret);
67 return UserAuthResultCode::OHOS_INVALID_PARAM;
68 }
69 IAM_LOGI("challenge size:%{public}zu", authParam_.challenge.size());
70 return UserAuthResultCode::SUCCESS;
71 }
72
InitAuthType(napi_env env,napi_value value)73 UserAuthResultCode UserAuthInstanceV10::InitAuthType(napi_env env, napi_value value)
74 {
75 bool isArray = false;
76 napi_is_array(env, value, &isArray);
77 if (!isArray) {
78 IAM_LOGI("authType is not array");
79 return UserAuthResultCode::OHOS_INVALID_PARAM;
80 }
81 uint32_t length = 0;
82 napi_get_array_length(env, value, &length);
83 for (uint32_t i = 0; i < length; ++i) {
84 napi_value jsValue = nullptr;
85 napi_handle_scope scope = nullptr;
86 napi_open_handle_scope(env, &scope);
87 napi_get_element(env, value, i, &jsValue);
88 if (jsValue == nullptr) {
89 napi_close_handle_scope(env, scope);
90 continue;
91 }
92 int32_t value = 0;
93 napi_status ret = UserAuthNapiHelper::GetInt32Value(env, jsValue, value);
94 napi_close_handle_scope(env, scope);
95 if (ret != napi_ok) {
96 IAM_LOGE("napi authType GetUint32Value fail:%{public}d", ret);
97 return UserAuthResultCode::OHOS_INVALID_PARAM;
98 }
99 IAM_LOGI("napi get authType:%{public}d", value);
100 if (!UserAuthNapiHelper::CheckUserAuthType(value)) {
101 IAM_LOGE("authType is illegal, %{public}d", value);
102 return UserAuthResultCode::TYPE_NOT_SUPPORT;
103 }
104 auto iter = std::find(authParam_.authType.begin(), authParam_.authType.end(), static_cast<AuthType>(value));
105 if (iter != authParam_.authType.end()) {
106 IAM_LOGE("napi authType:%{public}d exist", value);
107 return UserAuthResultCode::OHOS_INVALID_PARAM;
108 }
109 authParam_.authType.push_back(static_cast<AuthType>(value));
110 }
111
112 IAM_LOGI("authType size:%{public}zu", authParam_.authType.size());
113 return UserAuthResultCode::SUCCESS;
114 }
115
InitAuthParam(napi_env env,napi_value value)116 UserAuthResultCode UserAuthInstanceV10::InitAuthParam(napi_env env, napi_value value)
117 {
118 napi_status ret = UserAuthNapiHelper::CheckNapiType(env, value, napi_null);
119 if (ret == napi_ok) {
120 IAM_LOGI("authParam is null");
121 return UserAuthResultCode::OHOS_INVALID_PARAM;
122 }
123
124 if (!UserAuthNapiHelper::HasNamedProperty(env, value, AUTH_PARAM_CHALLENGE)) {
125 IAM_LOGE("propertyName: %{public}s not exists.", AUTH_PARAM_CHALLENGE.c_str());
126 return UserAuthResultCode::OHOS_INVALID_PARAM;
127 }
128 napi_value napi_challenge = UserAuthNapiHelper::GetNamedProperty(env, value, AUTH_PARAM_CHALLENGE);
129 UserAuthResultCode errorCode = InitChallenge(env, napi_challenge);
130 if (errorCode != UserAuthResultCode::SUCCESS) {
131 IAM_LOGE("InitChallenge fail:%{public}d", errorCode);
132 return UserAuthResultCode::OHOS_INVALID_PARAM;
133 }
134
135 if (!UserAuthNapiHelper::HasNamedProperty(env, value, AUTH_PARAM_AUTHTYPE)) {
136 IAM_LOGE("propertyName: %{public}s not exists.", AUTH_PARAM_AUTHTYPE.c_str());
137 return UserAuthResultCode::OHOS_INVALID_PARAM;
138 }
139 napi_value napi_authType = UserAuthNapiHelper::GetNamedProperty(env, value, AUTH_PARAM_AUTHTYPE);
140 errorCode = InitAuthType(env, napi_authType);
141 if (errorCode != UserAuthResultCode::SUCCESS) {
142 IAM_LOGE("InitAuthType fail:%{public}d", errorCode);
143 return errorCode;
144 }
145
146 if (!UserAuthNapiHelper::HasNamedProperty(env, value, AUTH_PARAM_AUTHTRUSTLEVEL)) {
147 IAM_LOGE("propertyName: %{public}s not exists.", AUTH_PARAM_AUTHTRUSTLEVEL.c_str());
148 return UserAuthResultCode::OHOS_INVALID_PARAM;
149 }
150
151 napi_value napi_authTrustLeval = UserAuthNapiHelper::GetNamedProperty(env, value, AUTH_PARAM_AUTHTRUSTLEVEL);
152 uint32_t authTrustLevel;
153 ret = UserAuthNapiHelper::GetUint32Value(env, napi_authTrustLeval, authTrustLevel);
154 if (ret != napi_ok) {
155 IAM_LOGE("GetUint32Value fail:%{public}d", ret);
156 return UserAuthResultCode::OHOS_INVALID_PARAM;
157 }
158 if (!UserAuthNapiHelper::CheckAuthTrustLevel(authTrustLevel)) {
159 IAM_LOGE("AuthTrustLeval fail:%{public}d", errorCode);
160 return UserAuthResultCode::TRUST_LEVEL_NOT_SUPPORT;
161 }
162 authParam_.authTrustLevel = AuthTrustLevel(authTrustLevel);
163
164 return UserAuthResultCode::SUCCESS;
165 }
166
InitWidgetParam(napi_env env,napi_value value)167 UserAuthResultCode UserAuthInstanceV10::InitWidgetParam(napi_env env, napi_value value)
168 {
169 napi_status ret = UserAuthNapiHelper::CheckNapiType(env, value, napi_null);
170 if (ret == napi_ok) {
171 IAM_LOGI("widgetParam is null");
172 return UserAuthResultCode::OHOS_INVALID_PARAM;
173 }
174
175 if (!UserAuthNapiHelper::HasNamedProperty(env, value, WIDGET_PARAM_TITLE)) {
176 IAM_LOGE("propertyName: %{public}s not exists.", WIDGET_PARAM_TITLE.c_str());
177 return UserAuthResultCode::OHOS_INVALID_PARAM;
178 }
179 std::string title = UserAuthNapiHelper::GetStringPropertyUtf8(env, value, WIDGET_PARAM_TITLE);
180 if (title == "" || title.length() > WidgetType::TITLE_MAX) {
181 IAM_LOGE("title is invalid. size: %{public}zu", title.length());
182 return UserAuthResultCode::OHOS_INVALID_PARAM;
183 }
184 widgetParam_.title = title;
185
186 if (UserAuthNapiHelper::HasNamedProperty(env, value, WIDGET_PARAM_NAVIBTNTEXT)) {
187 std::string naviBtnTxt = UserAuthNapiHelper::GetStringPropertyUtf8(env, value, WIDGET_PARAM_NAVIBTNTEXT);
188 if (naviBtnTxt == "" || naviBtnTxt.length() > WidgetType::BUTTON_MAX) {
189 IAM_LOGE("navigation button text is invalid, size: %{public}zu", naviBtnTxt.length());
190 return UserAuthResultCode::OHOS_INVALID_PARAM;
191 }
192 widgetParam_.navigationButtonText = naviBtnTxt;
193 }
194
195 if (UserAuthNapiHelper::HasNamedProperty(env, value, WIDGET_PARAM_WINDOWMODE)) {
196 napi_value napi_windowModeType = UserAuthNapiHelper::GetNamedProperty(env, value, WIDGET_PARAM_WINDOWMODE);
197 uint32_t windowMode;
198 ret = UserAuthNapiHelper::GetUint32Value(env, napi_windowModeType, windowMode);
199 if (ret != napi_ok) {
200 IAM_LOGE("napi authType GetUint32Value fail:%{public}d", ret);
201 return UserAuthResultCode::OHOS_INVALID_PARAM;
202 }
203 switch (windowMode) {
204 case WindowModeType::DIALOG_BOX:
205 case WindowModeType::FULLSCREEN:
206 widgetParam_.windowMode = static_cast<WindowModeType>(windowMode);
207 break;
208 default:
209 IAM_LOGE("windowMode type not support.");
210 return UserAuthResultCode::OHOS_INVALID_PARAM;
211 }
212 }
213
214 IAM_LOGI("widgetParam title:%{public}s, navBtnText:%{public}s, winMode:%{public}u",
215 widgetParam_.title.c_str(), widgetParam_.navigationButtonText.c_str(),
216 static_cast<uint32_t>(widgetParam_.windowMode));
217 return UserAuthResultCode::SUCCESS;
218 }
219
Init(napi_env env,napi_callback_info info)220 UserAuthResultCode UserAuthInstanceV10::Init(napi_env env, napi_callback_info info)
221 {
222 if (callback_ == nullptr) {
223 IAM_LOGE("callback is null");
224 return UserAuthResultCode::GENERAL_ERROR;
225 }
226 napi_value argv[ARGS_TWO];
227 size_t argc = ARGS_TWO;
228 napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
229 if (ret != napi_ok) {
230 IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
231 return UserAuthResultCode::GENERAL_ERROR;
232 }
233 if (argc != ARGS_TWO) {
234 IAM_LOGE("invalid param, argc:%{public}zu", argc);
235 return UserAuthResultCode::OHOS_INVALID_PARAM;
236 }
237
238 UserAuthResultCode errCode = InitAuthParam(env, argv[PARAM0]);
239 if (errCode != UserAuthResultCode::SUCCESS) {
240 IAM_LOGE("AuthParam type error, errorCode: %{public}d", errCode);
241 return errCode;
242 }
243
244 errCode = InitWidgetParam(env, argv[PARAM1]);
245 if (errCode != UserAuthResultCode::SUCCESS) {
246 IAM_LOGE("WidgetParam type error, errorCode: %{public}d", errCode);
247 return errCode;
248 }
249
250 IAM_LOGE("Init SUCCESS");
251 return UserAuthResultCode::SUCCESS;
252 }
253
GetCallback(napi_env env,napi_value value)254 std::shared_ptr<JsRefHolder> UserAuthInstanceV10::GetCallback(napi_env env, napi_value value)
255 {
256 napi_status ret = UserAuthNapiHelper::CheckNapiType(env, value, napi_object);
257 if (ret != napi_ok) {
258 IAM_LOGE("CheckNapiType fail:%{public}d", ret);
259 return nullptr;
260 }
261 napi_value callbackValue;
262 ret = napi_get_named_property(env, value, "onResult", &callbackValue);
263 if (ret != napi_ok) {
264 IAM_LOGE("napi_get_named_property fail:%{public}d", ret);
265 return nullptr;
266 }
267 return Common::MakeShared<JsRefHolder>(env, callbackValue);
268 }
269
On(napi_env env,napi_callback_info info)270 UserAuthResultCode UserAuthInstanceV10::On(napi_env env, napi_callback_info info)
271 {
272 if (callback_ == nullptr) {
273 IAM_LOGE("getAuthInstance on callback is null");
274 return UserAuthResultCode::GENERAL_ERROR;
275 }
276 napi_value argv[ARGS_TWO];
277 size_t argc = ARGS_TWO;
278 napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
279 if (ret != napi_ok) {
280 IAM_LOGE("getAuthInstance on napi_get_cb_info fail:%{public}d", ret);
281 return UserAuthResultCode::GENERAL_ERROR;
282 }
283 if (argc != ARGS_TWO) {
284 IAM_LOGE("getAuthInstance on invalid param, argc:%{public}zu", argc);
285 return UserAuthResultCode::OHOS_INVALID_PARAM;
286 }
287 static const size_t maxLen = 10;
288 char str[maxLen] = {0};
289 size_t len = maxLen;
290 ret = UserAuthNapiHelper::GetStrValue(env, argv[PARAM0], str, len);
291 if (ret != napi_ok) {
292 IAM_LOGE("getAuthInstance on GetStrValue fail:%{public}d", ret);
293 return UserAuthResultCode::OHOS_INVALID_PARAM;
294 }
295 auto callbackRef = GetCallback(env, argv[PARAM1]);
296 if (callbackRef == nullptr || !callbackRef->IsValid()) {
297 IAM_LOGE("getAuthInstance on GetCallback fail");
298 return UserAuthResultCode::OHOS_INVALID_PARAM;
299 }
300 if (str == AUTH_EVENT_RESULT) {
301 IAM_LOGI("getAuthInstance on SetResultCallback");
302 if (callback_->HasResultCallback()) {
303 IAM_LOGE("callback has been registerred");
304 return UserAuthResultCode::GENERAL_ERROR;
305 }
306 callback_->SetResultCallback(callbackRef);
307 return UserAuthResultCode::SUCCESS;
308 } else {
309 IAM_LOGE("getAuthInstance on invalid event:%{public}s", str);
310 return UserAuthResultCode::OHOS_INVALID_PARAM;
311 }
312 }
313
Off(napi_env env,napi_callback_info info)314 UserAuthResultCode UserAuthInstanceV10::Off(napi_env env, napi_callback_info info)
315 {
316 if (callback_ == nullptr) {
317 IAM_LOGE("userAuthInstance off callback is null");
318 return UserAuthResultCode::GENERAL_ERROR;
319 }
320 napi_value argv[ARGS_TWO];
321 size_t argc = ARGS_TWO;
322 napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
323 if (ret != napi_ok) {
324 IAM_LOGE("userAuthInstance off napi_get_cb_info fail:%{public}d", ret);
325 return UserAuthResultCode::GENERAL_ERROR;
326 }
327 if (argc != ARGS_TWO && argc != ARGS_ONE) {
328 IAM_LOGE("userAuthInstance off invalid param, argc:%{public}zu", argc);
329 return UserAuthResultCode::OHOS_INVALID_PARAM;
330 }
331 static const size_t maxLen = 10;
332 char str[maxLen] = {0};
333 size_t len = maxLen;
334 ret = UserAuthNapiHelper::GetStrValue(env, argv[PARAM0], str, len);
335 if (ret != napi_ok) {
336 IAM_LOGE("UserAuthResultCode off GetStrValue fail:%{public}d", ret);
337 return UserAuthResultCode::OHOS_INVALID_PARAM;
338 }
339
340 if (argc == ARGS_TWO) {
341 auto callbackRef = GetCallback(env, argv[PARAM1]);
342 if (callbackRef == nullptr || !callbackRef->IsValid()) {
343 IAM_LOGE("GetCallback fail");
344 return UserAuthResultCode::OHOS_INVALID_PARAM;
345 }
346 }
347
348 if (str == AUTH_EVENT_RESULT) {
349 if (!callback_->HasResultCallback()) {
350 IAM_LOGE("no callback registerred yet");
351 return UserAuthResultCode::GENERAL_ERROR;
352 }
353 callback_->ClearResultCallback();
354 IAM_LOGI("UserAuthResultCode off clear result callback");
355 return UserAuthResultCode::SUCCESS;
356 } else {
357 IAM_LOGE("invalid event:%{public}s", str);
358 return UserAuthResultCode::OHOS_INVALID_PARAM;
359 }
360 }
361
Start(napi_env env,napi_callback_info info)362 UserAuthResultCode UserAuthInstanceV10::Start(napi_env env, napi_callback_info info)
363 {
364 if (callback_ == nullptr) {
365 IAM_LOGE("callback is null");
366 return UserAuthResultCode::GENERAL_ERROR;
367 }
368 napi_value argv[ARGS_ONE];
369 size_t argc = ARGS_ONE;
370 napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
371 if (ret != napi_ok) {
372 IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
373 return UserAuthResultCode::GENERAL_ERROR;
374 }
375 if (argc != ARGS_ZERO) {
376 IAM_LOGE("invalid param, argc:%{public}zu", argc);
377 return UserAuthResultCode::OHOS_INVALID_PARAM;
378 }
379 std::lock_guard<std::mutex> guard(mutex_);
380 if (isAuthStarted_) {
381 IAM_LOGE("auth already started");
382 return UserAuthResultCode::GENERAL_ERROR;
383 }
384 contextId_ = UserAuthClientImpl::Instance().BeginWidgetAuth(API_VERSION_10,
385 authParam_, widgetParam_, callback_);
386 isAuthStarted_ = true;
387 return UserAuthResultCode::SUCCESS;
388 }
389
Cancel(napi_env env,napi_callback_info info)390 UserAuthResultCode UserAuthInstanceV10::Cancel(napi_env env, napi_callback_info info)
391 {
392 if (callback_ == nullptr) {
393 IAM_LOGE("callback is null");
394 return UserAuthResultCode::GENERAL_ERROR;
395 }
396 napi_value argv[ARGS_ONE];
397 size_t argc = ARGS_ONE;
398 napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
399 if (ret != napi_ok) {
400 IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
401 return UserAuthResultCode::GENERAL_ERROR;
402 }
403 if (argc != ARGS_ZERO) {
404 IAM_LOGE("invalid param, argc:%{public}zu", argc);
405 return UserAuthResultCode::OHOS_INVALID_PARAM;
406 }
407 std::lock_guard<std::mutex> guard(mutex_);
408 if (!isAuthStarted_) {
409 IAM_LOGE("auth not started");
410 return UserAuthResultCode::GENERAL_ERROR;
411 }
412 int32_t result = UserAuthClient::GetInstance().CancelAuthentication(contextId_);
413 if (result != ResultCode::SUCCESS) {
414 IAM_LOGE("CancelAuthentication fail:%{public}d", result);
415 return UserAuthResultCode(UserAuthNapiHelper::GetResultCodeV10(result));
416 }
417 isAuthStarted_ = false;
418 return UserAuthResultCode::SUCCESS;
419 }
420 } // namespace UserAuth
421 } // namespace UserIam
422 } // namespace OHOS
423