Настройка авторизации через OAUTH2 сервера https://oauth2.volmed.org.ru: различия между версиями

Материал из Wiki МИАЦ ВО
Перейти к навигации Перейти к поиску
(Формирование строки авторизации)
(Формирование POST запроса авторизации)
 
(не показаны 4 промежуточные версии этого же участника)
Строка 16: Строка 16:
 
</pre>
 
</pre>
 
#Для работы с JWT токеном используем библиотеку https://github.com/firebase/php-jwt. Ее нужно установить в каталог class/jwt
 
#Для работы с JWT токеном используем библиотеку https://github.com/firebase/php-jwt. Ее нужно установить в каталог class/jwt
 +
==Хранение пользовательских данных в COOKIES==
 +
Самое простое для моего случая - хранить в куках id пользователя и время создания куков. Тк все данные пользователя, я могу вытащить из БД по его id.<br>
 +
Их нужно зашифровать с помощью JWT и хранить полученное значение в куках.
 +
<pre>
 +
protected function set_cookie()
 +
{
 +
/*
 +
* Устанавливаем COOKIE
 +
*/
 +
  if (empty($this->login_expires_set)) {
 +
    $this->login_expires_set = 0;
 +
  }
 +
  if (empty($_COOKIE['jwt']) &&  !empty($this->auth['id'])) {
 +
    $payload = [
 +
      'id_user' => !empty($this->auth['id_real']) ? $this->auth['id_real'] : $this->auth['id'],
 +
      'time_beg' => time(),
 +
    ];
 +
    setcookie('jwt', JWT::encode($payload, $GLOBALS['jwt_key'], 'HS256'), [
 +
      "expires" => strtotime($this->login_expires_set),
 +
      "path" => "/",
 +
      "httponly" => true,
 +
    ]);
 +
  }
 +
}
 +
<pre>
 +
И проверка кукис
 +
<pre>
 +
protected function load_cookie()
 +
{
 +
  /*
 +
  * Метод по проверке COOKIE и загрузки их в переменные для проверки авторизации
 +
  */
 +
  if (!empty($_COOKIE['jwt'])) {
 +
      $decoded_obj = JWT::decode($_COOKIE['jwt'], new Key($GLOBALS['jwt_key'], 'HS256'));
 +
      $decoded = get_object_vars($decoded_obj);
 +
      $this->id_user = $decoded['id_user'];
 +
      $this->time_beg = $decoded['time_beg'];
 +
}
 +
}
 +
<pre>
 +
 
==Формирование строки авторизации==
 
==Формирование строки авторизации==
 
Для перехода на страницу сервера авторизации, генерим следующий код
 
Для перехода на страницу сервера авторизации, генерим следующий код
 
<pre>
 
<pre>
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
if (!empty($_GET['code'])) { // Если это уже ответ oauth2 сервера (Есть параметр state)
$state = generate_string($permitted_chars, 20); // Функция, которая генерит 20 символов из строки $permitted_chars
+
  if ($_GET['state'] == $_SESSION['state']) { // Если state совпадает с сохраненным в Сессии
$_SESSION['state'] = $state; // Сохраняем этот код, что бы потом его проверить на правильность
+
      $oauth2_access = $this->oauth2_post();  // Посылаем уже с помощью POST запрос
$url_data = [
+
      $this->auth = $this->auth($oauth2_access); // И после возврата id пользователя, обрабатываем его вход
  'response_type' => 'code',
+
  } else die('Ошибка авторизации (Invalid state), обратитесь к администраотру сайта');  // если state не совпал, то ошибка
  'client_id' => $GLOBALS['id_resource'],
+
} else { // Ето первый цикл обращения к oauth2 серверу
  'state' => $state,
+
  $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; // список символов, из которых будем генерить state
  'redirect_uri' => $GLOBALS['redirect_uri'] // Должен выглядеть как http://sait. volmed.org.ru
+
  $state = generate_string($permitted_chars, 20);   // Генерим код state - 20 символов случайного кода
 +
  $_SESSION['state'] = $state;   // Сохраняем в сессии
 +
  $url_data = [
 +
    'response_type' => 'code',
 +
    'client_id' => $GLOBALS['id_resource'],   // ID сервиса в МИАЦ
 +
    'state' => $state,                         // Случайный код, который сервис должен вернуть
 +
    'redirect_uri' => $GLOBALS['redirect_uri'] // Адрес возврата дб вв виде https://sait.volmed.org.ru
 +
  ];
 +
  $url = $GLOBALS['oauth2_url'] . '?' . http_build_query($url_data);    // URL для отправки на сервер авторизации
 +
  header('Location:' . $url); //
 +
  exit;
 +
}
 +
</pre>
 +
После перехода на сервер авторизации, вводим Логин и Пароль. И если он правильный, то сервер возвращает на страницу редиректа
 +
 
 +
==Формирование POST запроса авторизации==
 +
<pre>
 +
private function oauth2_post()
 +
{
 +
  $post_data = [
 +
  "user_id" => $_GET['user_id'],          // ID пользователя, возвращенного oauth2 серверром
 +
  "code" => $_GET['code'],
 +
  'grant_type' => 'authorization_code',    // Тип гранта
 +
  'client_id' => $GLOBALS['id_resource'],  // ID сервиса
 +
  'client_secret' => 'wetreyrtbv:KJLKO',  // это код из БД OUTH2 сервера таблица oauth_clients.client_secret для $GLOBALS['id_resource']
 +
  'redirect_uri' => $GLOBALS['redirect_uri'],
 +
  // 'scope' => 'read write',
 
];
 
];
$url = $GLOBALS['oauth2_url'] . '?' . http_build_query($url_data); // генерим строку перехода
+
  $data_string = json_encode($post_data);
header('Location:' . $url); // Переходим на сервер авторизации
+
  $ch = curl_init();
 +
  curl_setopt($ch, CURLOPT_URL, $GLOBALS['oauth2_url'] . '/token');
 +
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 +
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
 +
  curl_setopt($ch, CURLOPT_POST, true);
 +
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
 +
  curl_setopt($ch, CURLOPT_HTTPHEADER, array(
 +
'Content-Type: application/json',
 +
'Content-Length: ' . strlen($data_string),
 +
));
 +
  $oauth2_access = [];
 +
  $output = curl_exec($ch);
 +
  // execute the request
 +
  if ($output === false) echo 'Ошибка curl: ' . curl_error($ch);
 +
  else {
 +
    $oauth2_access = json_decode($output, true);
 +
    if (!empty($oauth2_access['error'])) {
 +
        printr($oauth2_access);
 +
        exit();
 +
    }
 +
    $oauth2_access['id_user'] = $_GET['user_id'];
 +
  }
 +
        curl_close($ch);
 +
        return $oauth2_access;
 +
    }
 +
</pre>
 +
==Запрос пользовательских данных==
 +
<pre>
 +
public function take_userinfo()
 +
{
 +
  $accessToken = $this->access_token; // <-- access token
 +
  $userInfoUrl = $GLOBALS['oauth2_url'] . '/userinfo'; // <-- endpoint
 +
 
 +
  $ch = curl_init();
 +
 
 +
  curl_setopt($ch, CURLOPT_URL, $userInfoUrl);
 +
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 +
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
 +
    'Authorization: Bearer ' . $accessToken,
 +
    'Accept: application/json'
 +
  ]);
 +
 
 +
  $response = curl_exec($ch);
 +
  $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
 +
 
 +
  if (curl_errno($ch)) {
 +
      echo 'Ошибка cURL: ' . curl_error($ch);
 +
  } elseif ($httpCode !== 200) {
 +
      echo "Ошибка HTTP $httpCode: $response";
 +
  } else {
 +
    $userData = json_decode($response, true);
 +
    //printr($userData);
 +
  }
 +
 
 +
  curl_close($ch);
 +
  return $userData;
 +
}
 
</pre>
 
</pre>
После перехода на сервер авторизации, вводим Логин и Пароль. И если он правильный, то сервер возвращает на страницу редиректа
 

Текущая версия на 10:55, 7 мая 2025

Подготовительные операции

  1. Идем в БД oauth_db на сервере 172.16.130.31 и добавляем в таблицу oauth_clients
    1. client_id - Номер WEB интерфейса, который вы собираетесь подключить
    2. client_secret - Набор любых символов для шифрования
  2. Добавляем в настроечный файл сервиса следующие строки
$GLOBALS['id_resource'] = 7; // Номер WEB интерфейса
$PassLength=5; //длина пароля
$GLOBALS['jwt_key'] = 'sdklfwiomwefwepiojwepjowfmwfmwef'; // Строка с набором символов для шифрования JWT токена
$GLOBALS['max_time'] = 3600 * 24 * 7; // Время жизни COOKIES, например, 7 суток

$oauth2_url = 'https://oauth2.volmed.org.ru';    // URL сервиса авторизации
$GLOBALS['oauth2_url'] = $oauth2_url;
$redirect_uri =  $http."://$_SERVER[HTTP_HOST]";
$GLOBALS['redirect_uri'] = $redirect_uri;
  1. Для работы с JWT токеном используем библиотеку https://github.com/firebase/php-jwt. Ее нужно установить в каталог class/jwt

Хранение пользовательских данных в COOKIES

Самое простое для моего случая - хранить в куках id пользователя и время создания куков. Тк все данные пользователя, я могу вытащить из БД по его id.
Их нужно зашифровать с помощью JWT и хранить полученное значение в куках.

protected function set_cookie()
{
/*
 * Устанавливаем COOKIE
*/
  if (empty($this->login_expires_set)) {
     $this->login_expires_set = 0;
  }
  if (empty($_COOKIE['jwt']) &&  !empty($this->auth['id'])) {
     $payload = [
      'id_user' => !empty($this->auth['id_real']) ? $this->auth['id_real'] : $this->auth['id'],
      'time_beg' => time(),
     ];
     setcookie('jwt', JWT::encode($payload, $GLOBALS['jwt_key'], 'HS256'), [
       "expires" => strtotime($this->login_expires_set),
       "path" => "/",
       "httponly" => true,
     ]);
  }
}
<pre>
И проверка кукис
<pre>
protected function load_cookie()
{
  /*
  * Метод по проверке COOKIE и загрузки их в переменные для проверки авторизации
  */
  if (!empty($_COOKIE['jwt'])) {
      $decoded_obj = JWT::decode($_COOKIE['jwt'], new Key($GLOBALS['jwt_key'], 'HS256'));
      $decoded = get_object_vars($decoded_obj);
      $this->id_user = $decoded['id_user'];
      $this->time_beg = $decoded['time_beg'];
 }
}
<pre>

==Формирование строки авторизации==
Для перехода на страницу сервера авторизации, генерим следующий код
<pre>
if (!empty($_GET['code'])) { // Если это уже ответ oauth2 сервера (Есть параметр state)
   if ($_GET['state'] == $_SESSION['state']) { // Если state совпадает с сохраненным в Сессии
      $oauth2_access = $this->oauth2_post();   // Посылаем уже с помощью POST запрос
      $this->auth = $this->auth($oauth2_access); // И после возврата id пользователя, обрабатываем его вход
   } else die('Ошибка авторизации (Invalid state), обратитесь к администраотру сайта');  // если state не совпал, то ошибка
} else { // Ето первый цикл обращения к oauth2 серверу
   $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';  // список символов, из которых будем генерить state
   $state = generate_string($permitted_chars, 20);   // Генерим код state - 20 символов случайного кода
   $_SESSION['state'] = $state;   // Сохраняем в сессии
   $url_data = [
     'response_type' => 'code',
     'client_id' => $GLOBALS['id_resource'],    // ID сервиса в МИАЦ
     'state' => $state,                         // Случайный код, который сервис должен вернуть
     'redirect_uri' => $GLOBALS['redirect_uri'] // Адрес возврата дб вв виде https://sait.volmed.org.ru
  ];
  $url = $GLOBALS['oauth2_url'] . '?' . http_build_query($url_data);    // URL для отправки на сервер авторизации
  header('Location:' . $url); //
  exit;
}

После перехода на сервер авторизации, вводим Логин и Пароль. И если он правильный, то сервер возвращает на страницу редиректа

Формирование POST запроса авторизации

private function oauth2_post()
{
  $post_data = [
  "user_id" => $_GET['user_id'],           // ID пользователя, возвращенного oauth2 серверром
  "code" => $_GET['code'],
  'grant_type' => 'authorization_code',    // Тип гранта
  'client_id' => $GLOBALS['id_resource'],   // ID сервиса
  'client_secret' => 'wetreyrtbv:KJLKO',   // это код из БД OUTH2 сервера таблица oauth_clients.client_secret для $GLOBALS['id_resource']
  'redirect_uri' => $GLOBALS['redirect_uri'],
  // 'scope' => 'read write',
];
  $data_string = json_encode($post_data);
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $GLOBALS['oauth2_url'] . '/token');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array(
 'Content-Type: application/json',
 'Content-Length: ' . strlen($data_string),
 ));
  $oauth2_access = [];
  $output = curl_exec($ch);
  // execute the request
  if ($output === false) echo 'Ошибка curl: ' . curl_error($ch);
  else {
     $oauth2_access = json_decode($output, true);
     if (!empty($oauth2_access['error'])) {
         printr($oauth2_access);
         exit();
     }
     $oauth2_access['id_user'] = $_GET['user_id'];
  }
        curl_close($ch);
        return $oauth2_access;
    }

Запрос пользовательских данных

public function take_userinfo()
{
   $accessToken = $this->access_token; // <-- access token
   $userInfoUrl = $GLOBALS['oauth2_url'] . '/userinfo'; // <-- endpoint

   $ch = curl_init();

   curl_setopt($ch, CURLOPT_URL, $userInfoUrl);
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
   curl_setopt($ch, CURLOPT_HTTPHEADER, [
     'Authorization: Bearer ' . $accessToken,
     'Accept: application/json'
   ]);

   $response = curl_exec($ch);
   $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

   if (curl_errno($ch)) {
      echo 'Ошибка cURL: ' . curl_error($ch);
   } elseif ($httpCode !== 200) {
      echo "Ошибка HTTP $httpCode: $response";
   } else {
     $userData = json_decode($response, true);
     //printr($userData);
   }

  curl_close($ch);
  return $userData;
}