Благодарим за внимание
Пакет заоперсорсен финтех-компанией в которой я работаю. Не тестировалось на животных.
Как обновить токен?
Стандартно, как описано в документации к oauth2-client
Как организации подключиться к есиа
Юридические лица подключаются к ЕСИА через личный кабинет руководителя. Для подключения используется функция «Добавить организацию» и выбирается необходимый статус: ИП, организация, орган власти.
Для формирования учётной записи юридического лица необходимо, чтобы у руководителя была подтвержденная учётная запись. Для подключения к системе используется квалифицированная электронная подпись, сертификат которой оформлен на руководителя.
При регистрации юрлица потребуется заполнить все данные об организации, указанные в регистрационной форме. После проверки сведений и их подтверждения (это делается в автоматическом режиме) будет создана учётная запись организации в ЕСИА.
Дополнительная возможность для учётных записей организаций — подключение авторизации пользователей через ЕСИА для доступа к сайту или другому интернет-ресурсу организации. Для этого нужно предоставить сведения о подключаемой системе, при необходимости доработать её под требования ЕСИА, запустить работу подключённой системы в тестовом режиме, а после подтверждения работоспособности — в рабочем режиме.
Получаем данные пользователя
Проверяя стейт и меняя код на аутентификационный токен.
Редиректим посетителя на есиа
Одновременно сохраняя стейт для последующей проверки.
Рецепты nginx: авторизация через есиа
Для приготовления авторизации через ЕСИА нам понадобится сам
nginx
и его плагины
encrypted-session
,
headers-more
,
auth_request
,
uuid4
,
set-misc
,
echo
,
json
,
sign
,
jwt
. (Я дал ссылки на свои форки, т.к. делал некоторые изменения, которые пока не удалось пропихнуть в оригинальные репозитории. Можно также воспользоваться
готовым образом
.)
Для начала зададим
encrypted_session_key "abcdefghijklmnopqrstuvwxyz123456";
Дальше, на всякий случай, отключаем авторизационный заголовок
more_clear_input_headers Authorization;
Теперь защищаем всё авторизацией
auth_request /auth;
location =/auth {
internal;
set_decode_base64 $auth_decode $cookie_auth; # раскодируем авторизационную куку
set_decrypt_session $auth_decrypt $auth_decode; # расшифровываем авторизационную куку
if ($auth_decrypt = "") { return 401 UNAUTHORIZED; } # если не удалось расшифровать, то значит пользователь не авторизован
more_set_input_headers "Authorization: Basic $auth_decrypt"; # подменить авторизацию на basic (чтобы использовать переменную $remote_user)
echo -n OK; # пользователь авторизован
}
Для авторизованных пользователей показываем контент из их папки
location / {
alias html/$remote_user/;
}
А при отсутствии авторизации перенаправляем на ЕСИА
error_page 401 = @error401;
location @error401 {
set $client_id мнемоника; # задаём мнемонику ЕСИА
set $scope openid; # задаём запрашиваемые скоупы
uuid4 $state; # генерируем случайное состояние
set_formatted_local_time $timestamp "%Y.%m.%d %H:%M:%S %z"; # задаем дату-время в требуемом ЕСИА формате
sign_certificate /data/nginx/esia.crt; # задаём сертификат (который мы загрузили в ЕСИА)
sign_certificate_key /data/nginx/esia.key; # задаём приватный ключ
sign_set $client_secret $scope$timestamp$client_id$state; # подписываем необходимые ЕСИА параметры
set_escape_uri $access_type_escape online; # задаём необходимый ЕСИА способ доступа и кодируем его
set_escape_uri $client_id_escape $client_id; # кодируем мнемонику
set_escape_uri $client_secret_escape $client_secret; # кодируем подпись
set_escape_uri $request_uri_escape $request_uri; # кодируем исходный запрос
set_escape_uri $redirect_uri_escape $scheme://$server_name:$server_port/login?request_uri=$request_uri_escape; # задаём и кодируем адрес возврата
set_escape_uri $response_type_escape code; # задаём и кодируем тип ответа
set_escape_uri $scope_escape $scope; # кодируем скоупы
set_escape_uri $state_escape $state; # кодируем состояние
set_escape_uri $timestamp_escape $timestamp; # кодируем дату-время
return 303 https://esia.gosuslugi.ru/aas/oauth2/ac?access_type=$access_type_escape&client_id=$client_id_escape&client_secret=$client_secret_escape&redirect_uri=$redirect_uri_escape&response_type=$response_type_escape&scope=$scope_escape&state=$state_escape×tamp=$timestamp_escape; # перенаправляем на ЕСИА
После успешной авторизации пользователя в ЕСИА, его перенаправляет на адрес возврата
location =/login {
auth_request off; # не использовать авторизацию
auth_jwt_key /data/nginx/esia.pub file; # задаём публичный ключ (который мы получили от ЕСИА) для расшифровки токена
auth_jwt $arg_code; # задаём токен
json_loads $jwt_grant_json $jwt_grant; # парсим тело токена в переменную
json_dumps $oid $jwt_grant_json urn:esia:sbj urn:esia:sbj:oid; # извлекаем oid
try_files /try?username=$oid; # перенаправляем на дальнейшую обработку
}
location =/try {
internal;
if ($arg_username = "") { return 401 UNAUTHORIZED; } # если oid не получен, то значит пользователь не авторизован
encrypted_session_expires 43200; # задаём время жизни сессии 12 часов (12 * 60 * 60 = 43200)
set_secure_random_alphanum $password 8; # задаём случайный пароль для basic авторизации
set $username_password ESIA-$arg_username:$password; # задаём basic авторизацию
set_encode_base64 $username_password_encode $username_password; # кодируем basic авторизацию
set_encrypt_session $auth_encrypt $username_password_encode; # зашифровываем basic авторизацию
set_encode_base64 $auth_encode $auth_encrypt; # кодируем зашифрованную basic авторизацию
add_header Set-Cookie "Auth=$auth_encode; Max-Age=43200"; # помещаем зашифрованную basic авторизацию в авторизационную куку на 12 часов (12 * 60 * 60 = 43200)
set $arg_request_uri_or_slash $arg_request_uri; # копируем запрос из аргумента
set_if_empty $arg_request_uri_or_slash "/"; # если аргумент не задан, то начало
set_unescape_uri $request_uri_unescape $arg_request_uri_or_slash; # раскодируем запрос
return 303 $request_uri_unescape; # перенаправляем на сохранённый запрос
}