From 50c5d3997517e0693140330f9c68fb141b137073 Mon Sep 17 00:00:00 2001 From: Sergei Jeihala Date: Mon, 17 Apr 2023 14:23:44 +0300 Subject: [PATCH] Authorization update --- modules/yadevices/auth.inc.php | 202 ++++++++++++++++++++++++++ modules/yadevices/yadevices.class.php | 29 ++++ templates/yadevices/action_admin.html | 17 ++- templates/yadevices/auth.html | 62 ++++++++ templates/yadevices/auth_cookie.html | 16 ++ templates/yadevices/auth_otp.html | 26 ++++ templates/yadevices/auth_qr.html | 19 +++ 7 files changed, 366 insertions(+), 5 deletions(-) create mode 100644 modules/yadevices/auth.inc.php create mode 100644 templates/yadevices/auth.html create mode 100644 templates/yadevices/auth_cookie.html create mode 100644 templates/yadevices/auth_otp.html create mode 100644 templates/yadevices/auth_qr.html diff --git a/modules/yadevices/auth.inc.php b/modules/yadevices/auth.inc.php new file mode 100644 index 0000000..eac6584 --- /dev/null +++ b/modules/yadevices/auth.inc.php @@ -0,0 +1,202 @@ +refreshDevices(); +} + +if ($type == 'reset') { + @unlink(YADEVICES_COOKIE_PATH); + $this->redirect("?view_mode=" . $this->view_mode); +} + +if ($type == 'otp') { + $track_id = gr('track_id'); + if ($track_id) { + $otp = gr('otp'); + if ($otp!='') { + $post = array( + 'csrf_token' => gr('csrf_token'), + 'track_id' => $track_id, + 'password' => $otp, + 'retpath' => 'https://passport.yandex.ru/am/finish?status=ok&from=Login', + ); + $postvars = ''; + foreach($post as $key=>$value) { + $postvars .= $key . "=" . urlencode($value) . "&"; + } + $YaCurl = curl_init(); + curl_setopt($YaCurl, CURLOPT_URL, 'https://passport.yandex.ru/registration-validations/auth/multi_step/commit_password'); + curl_setopt($YaCurl, CURLOPT_POST, true); + curl_setopt($YaCurl, CURLOPT_POSTFIELDS, $postvars); + curl_setopt($YaCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($YaCurl, CURLOPT_COOKIEFILE, YADEVICES_COOKIE_PATH); + curl_setopt($YaCurl, CURLOPT_COOKIEJAR, YADEVICES_COOKIE_PATH); + $result = curl_exec($YaCurl); + curl_close($YaCurl); + $data = json_decode($result, true); + if ($data['status']=='ok' || $data['errors'][0]=='account.auth_passed') { + $checkCookie = $this->apiRequest('https://iot.quasar.yandex.ru/m/user/scenarios'); + if ($checkCookie['status'] != 'ok') { + @unlink(YADEVICES_COOKIE_PATH); + $out['ERR_MSG'] = 'Ошибка авторизации!'; + return; + } else { + $this->redirect("?view_mode=" . $this->view_mode . "&refresh_devices=1&ok_msg=" . urlencode("Успешная авторизация!")); + } + } else { + $out['ERR_MSG'] = 'Авторизация не пройдена. Попробуйте ещё раз.'; + } + } + $out['TRACK_ID']=$track_id; + } else { + $username = gr('username'); + if ($username) { + $csrf_token = $this->getCSRFToken(); + if ($csrf_token!='') { + $out['CSRF_TOKEN'] = $csrf_token; + $post = array( + 'csrf_token' => $csrf_token, + 'login' => $username, + ); + $postvars = ''; + foreach($post as $key=>$value) { + $postvars .= $key . "=" . urlencode($value) . "&"; + } + $YaCurl = curl_init(); + curl_setopt($YaCurl, CURLOPT_URL, 'https://passport.yandex.ru/registration-validations/auth/multi_step/start'); + curl_setopt($YaCurl, CURLOPT_POST, true); + curl_setopt($YaCurl, CURLOPT_POSTFIELDS, $postvars); + curl_setopt($YaCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($YaCurl, CURLOPT_COOKIEFILE, YADEVICES_COOKIE_PATH); + curl_setopt($YaCurl, CURLOPT_COOKIEJAR, YADEVICES_COOKIE_PATH); + $result = curl_exec($YaCurl); + curl_close($YaCurl); + $data = json_decode($result, true); + if ($data['status']=='ok') { + $track_id = $data['track_id']; + $out['TRACK_ID']=$track_id; + } else { + $out['ERR_MSG']='Ошибка авторизации. Попробуйте ещё раз.'; + } + + } else { + $out['ERR_MSG'] = 'Ошибка получения CSRF-токена'; + } + } + + } +} + +if ($type == 'qr') { + $track_id = gr('track_id'); + if ($track_id) { + $csrf_token = gr('csrf_token'); + $post = array( + 'csrf_token' => $csrf_token, + 'track_id' => $track_id, + ); + $postvars = ''; + foreach($post as $key=>$value) { + $postvars .= $key . "=" . urlencode($value) . "&"; + } + + $YaCurl = curl_init(); + $url = 'https://passport.yandex.ru/auth/magic/status/'; + + curl_setopt($YaCurl, CURLOPT_URL, $url); + curl_setopt($YaCurl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0'); + curl_setopt($YaCurl, CURLOPT_POST, true); + curl_setopt($YaCurl, CURLOPT_POSTFIELDS, $postvars); + curl_setopt($YaCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($YaCurl, CURLOPT_COOKIEFILE, YADEVICES_COOKIE_PATH); + curl_setopt($YaCurl, CURLOPT_COOKIEJAR, YADEVICES_COOKIE_PATH); + $result = curl_exec($YaCurl); + curl_close($YaCurl); + + $data = json_decode($result, true); + + if ($data['status']=='ok' || $data['errors'][0]=='account.auth_passed') { + $checkCookie = $this->apiRequest('https://iot.quasar.yandex.ru/m/user/scenarios'); + if ($checkCookie['status'] != 'ok') { + @unlink(YADEVICES_COOKIE_PATH); + $out['ERR_MSG'] = 'Ошибка авторизации!'; + return; + } else { + $this->redirect("?view_mode=" . $this->view_mode . "&refresh_devices=1&ok_msg=" . urlencode("Успешная авторизация!")); + } + } else { + $out['ERR_MSG'] = 'Авторизация не пройдена. Попробуйте ещё раз.'; + } + + $out['TRACK_ID'] = $track_id; + $out['QR_URL'] = 'https://passport.yandex.ru/auth/magic/code/?track_id=' . $track_id; + $out['CSRF_TOKEN'] = $csrf_token; + + } else { + $csrf_token = $this->getCSRFToken(); + if ($csrf_token) { + $post = array( + 'csrf_token' => $csrf_token, + 'retpath' => 'https://passport.yandex.ru/profile', + 'with_code' => 1, + ); + + $postvars = ''; + foreach($post as $key=>$value) { + $postvars .= $key . "=" . urlencode($value) . "&"; + } + $YaCurl = curl_init(); + curl_setopt($YaCurl, CURLOPT_URL, 'https://passport.yandex.ru/registration-validations/auth/password/submit'); + curl_setopt($YaCurl, CURLOPT_POST, true); + curl_setopt($YaCurl, CURLOPT_POSTFIELDS, $postvars); + curl_setopt($YaCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($YaCurl, CURLOPT_COOKIEFILE, YADEVICES_COOKIE_PATH); + curl_setopt($YaCurl, CURLOPT_COOKIEJAR, YADEVICES_COOKIE_PATH); + $result = curl_exec($YaCurl); + curl_close($YaCurl); + + $data = json_decode($result, true); + if ($data['status'] == 'ok') { + $out['TRACK_ID'] = $data['track_id']; + $out['CSRF_TOKEN'] = $data['csrf_token']; + $out['QR_URL'] = 'https://passport.yandex.ru/auth/magic/code/?track_id=' . $data['track_id']; + } else { + $out['ERR_MSG'] = 'Ошибка получения QR-кода'; + } + } else { + $out['ERR_MSG'] = 'Ошибка получения CSRF-токена'; + } + } +} + +if ($type == 'cookie') { + global $file; + if (is_file($file)) { + move_uploaded_file($file, YADEVICES_COOKIE_PATH); + $checkCookie = $this->apiRequest('https://iot.quasar.yandex.ru/m/user/scenarios'); + if ($checkCookie['status'] != 'ok') { + @unlink(YADEVICES_COOKIE_PATH); + $out['ERR_MSG'] = 'Файл который вы загружаете не является Cookie файлом с сайта Яндекс или он устарел.'; + return; + } else { + $this->redirect("?view_mode=" . $this->view_mode . "&refresh_devices=1&ok_msg=" . urlencode("Успешная авторизация!")); + } + } +} + +if (!$type) { + $data = $this->apiRequest('https://iot.quasar.yandex.ru/m/user/devices'); + if (is_array($data)) { + $out['AUTHORIZED_OK'] = 1; + } + +} diff --git a/modules/yadevices/yadevices.class.php b/modules/yadevices/yadevices.class.php index 543d3ff..595d75c 100644 --- a/modules/yadevices/yadevices.class.php +++ b/modules/yadevices/yadevices.class.php @@ -239,6 +239,10 @@ function admin(&$out) $out['SET_DATASOURCE'] = 1; } + if ($this->view_mode == 'auth') { + $this->auth($out); + } + if ($this->view_mode == 'refreshScenarios') { $this->addScenarios(); @@ -382,6 +386,10 @@ function admin(&$out) $out['ERRORMONITORTYPE'] = $this->config['ERRORMONITORTYPE']; } + function auth(&$out) { + include_once(DIR_MODULES.'yadevices/auth.inc.php'); + } + function fixOAUTHToken() { // getAuth token @@ -939,6 +947,27 @@ function apiRequest($url, $method = 'GET', $params = 0, $repeating = 0) return $data; } + function getCSRFToken() { + $YaCurl = curl_init(); + curl_setopt($YaCurl, CURLOPT_URL, 'https://passport.yandex.ru/am?app_platform=android'); + curl_setopt($YaCurl, CURLOPT_COOKIEFILE, YADEVICES_COOKIE_PATH); + curl_setopt($YaCurl, CURLOPT_COOKIEJAR, YADEVICES_COOKIE_PATH); + curl_setopt($YaCurl, CURLOPT_HEADER, 1); + curl_setopt($YaCurl, CURLOPT_POST, false); + curl_setopt($YaCurl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($YaCurl, CURLOPT_VERBOSE, false); + curl_setopt($YaCurl, CURLOPT_FOLLOWLOCATION, 1); + $result = curl_exec($YaCurl); + curl_close($YaCurl); + + if (preg_match('/"csrf_token" value="(.+?)"/', $result, $m)) { + $token = $m[1]; + return $token; + } else { + return false; + } + } + function getToken() { //Получение токенов для отправки запросов в Яндекс diff --git a/templates/yadevices/action_admin.html b/templates/yadevices/action_admin.html index 0da2796..da3feed 100644 --- a/templates/yadevices/action_admin.html +++ b/templates/yadevices/action_admin.html @@ -1,6 +1,3 @@ -[#if OAUTH_TOKEN == ''#] - [#inc login_form.html#] -[#else#]
@@ -9,13 +6,14 @@
Баги и обсуждение - [#if COOKIE_FILE == 1#] [#if VIEW_MODE="search_yastations" || VIEW_MODE="" || VIEW_MODE="search_yadevices"#] Обновить [#endif#] Настройки [#endif#] + Авторизация + | Выход
@@ -27,7 +25,13 @@ [#if COOKIE_FILE != 1#] [#if VIEW_MODE="search_yastations" || VIEW_MODE=""#] + + +

Авторизация

+

Для корректной работы модуля необходимо пройти авторизацию.

+ [#endif VIEW_MODE#] [#endif#] @@ -57,6 +61,10 @@
 
+[#if VIEW_MODE="auth"#] +[#inc auth.html#] +[#endif#] + [#if VIEW_MODE="search_yastations" || VIEW_MODE=""#] [#inc yastations_search_admin.html#] @@ -83,4 +91,3 @@ [#endif VIEW_MODE#] -[#endif#] \ No newline at end of file diff --git a/templates/yadevices/auth.html b/templates/yadevices/auth.html new file mode 100644 index 0000000..36c8e14 --- /dev/null +++ b/templates/yadevices/auth.html @@ -0,0 +1,62 @@ +

Авторизация

+[#if ERR_MSG!=""#] +
[#ERR_MSG#]
+[#endif ERR_MSG#] + +[#if OK_MSG!=""#] +
[#OK_MSG#]
+[#endif OK_MSG#] + +[#if TYPE=""#] +
+ Состояние авторизации: + [#if AUTHORIZED_OK="1"#] + Авторизовано + + Удалить авторизацию + + [#else#] + Не авторизовано + [#endif#] +
+  +

Выберите способ авторизации:

+ + + + + + + + + + + + + +
+ QR-код + + Авторизация по QR-коду с помощью приложения Я.Ключ +
+ Одноразовый пароль + + Авторизация с помощью одноразового пароля +
+ Cookie-файл + + Загрузка cookie-файла +
+[#endif TYPE#] + +[#if TYPE="otp"#] +[#inc auth_otp.html#] +[#endif TYPE#] + +[#if TYPE="cookie"#] +[#inc auth_cookie.html#] +[#endif TYPE#] + +[#if TYPE="qr"#] +[#inc auth_qr.html#] +[#endif TYPE#] \ No newline at end of file diff --git a/templates/yadevices/auth_cookie.html b/templates/yadevices/auth_cookie.html new file mode 100644 index 0000000..f5babd7 --- /dev/null +++ b/templates/yadevices/auth_cookie.html @@ -0,0 +1,16 @@ +

+ Для работы данного способа, необходимо скачать файл с данными Cookie сформированный на странице Yandex IOT. + После скачивания файла его необходимо загрузить в данную форму. +

+
+
+ +
+   + + + +
\ No newline at end of file diff --git a/templates/yadevices/auth_otp.html b/templates/yadevices/auth_otp.html new file mode 100644 index 0000000..eee748b --- /dev/null +++ b/templates/yadevices/auth_otp.html @@ -0,0 +1,26 @@ +

+ Авторизация происходит с помощью одноразового пароля, доступного в приложении Я.Ключ. Пароль действует 30 секунд. +

+ +
+ [#if TRACK_ID!=""#] +
+ + +
+ + [#else TRACK_ID#] +
+ + +
+ [#endif TRACK_ID#] +   + + + + +
diff --git a/templates/yadevices/auth_qr.html b/templates/yadevices/auth_qr.html new file mode 100644 index 0000000..f00aed0 --- /dev/null +++ b/templates/yadevices/auth_qr.html @@ -0,0 +1,19 @@ +

+ Для работы данного способа, необходимо отсанировать QR-код с помощью приложения Я.Ключ, войти в аккаунт через приложение и нажать "Продолжить" форме ниже. +

+
+ [#if QR_URL!=""#] +
+ +
+ [#endif QR_URL#] + + + + + + +
\ No newline at end of file