Рецепты Nginx: авторизация через auth0

от автора

Для приготовления авторизации через auth0 нам понадобится сам nginx и его плагины encrypted-session, headers-more, auth_request, set-misc, echo, json, evaluate и jwt. Можно также воспользоваться готовым образом.

Для начала, получим публичный ключ командой

curl https://our.application.domain.com/pem | openssl x509 -pubkey -noout > pub.key

Теперь, в конфиге зададим

encrypted_session_key "abcdefghijklmnopqrstuvwxyz123456";

Дальше отключаем авторизационный заголовок

more_clear_input_headers Authorization;

Теперь защищаем всё авторизацией

auth_request @auth; location @auth {   # если нет авторизационной куки, то значит пользователь не авторизован     if ($cookie_auth = "") { return 401 UNAUTHORIZED; }   # раскодируем авторизационную куку     set_decode_base64 $auth_decode $cookie_auth;   # если не удалось раскодировать, то значит пользователь не авторизован     if ($auth_decode = "") { return 401 UNAUTHORIZED; }   # расшифровываем авторизационную куку     set_decrypt_session $auth_decrypt $auth_decode;   # если не удалось расшифровать, то значит пользователь не авторизован     if ($auth_decrypt = "") { return 401 UNAUTHORIZED; }   # подменяем авторизацию на basic (чтобы использовать переменную $remote_user)     more_set_input_headers "Authorization: Basic $auth_decrypt";     echo -n OK; # пользователь авторизован }

Для авторизованных пользователей показываем контент из их папки

location / {     alias html/$remote_user/; }

А при отсутствии авторизации перенаправляем на auth0

error_page 401 = @error; location @error {   # задаём домен нашего приложения на auth0     set $domain our.application.domain.com;   # задаём и кодируем идентификатор нашего приложения на auth0     set_escape_uri $client_id_escape YourApplicationClientID;   # кодируем исходный запрос     set_escape_uri $request_uri_escape $request_uri;   # задаём и кодируем адрес возврата     set_escape_uri $redirect_uri_escape https://$host/login?request_uri=$request_uri_escape;   # задаём и кодируем тип ответа     set_escape_uri $response_type_escape code;   # задаём и кодируем скоупы     set_escape_uri $scope_escape "openid profile";   # задаём и кодируем состояние     set_escape_uri $state_escape 0;   # перенаправляем клиента на auth0     return 303 https://$domain/authorize?client_id=$client_id_escape&redirect_uri=$redirect_uri_escape&response_type=$response_type_escape&scope=$scope_escape&state=$state_escape; }

После успешной авторизации пользователя в auth0, его перенаправляет на адрес возврата

location =/login {     auth_request off; # не используем авторизацию     evaluate $grant /grant; # получаем грант     json_loads $grant_json $grant; # загружаем его     json_dumps $aud $grant_json aud; # извлекаем идентификатор   # если идентификатор не получен, то значит пользователь не авторизован   if ($aud = "") { return 401 UNAUTHORIZED; }     json_dumps $name $grant_json name; # извлекаем имя   # задаём случайный пароль для basic авторизации     set_secure_random_alphanum $password 8;   # задаём и кодируем basic авторизацию     set_encode_base64 $username_password_encode $name:$password;   # зашифровываем basic авторизацию на 12 часов (12 * 60 * 60 = 43200)     set_encrypt_session $auth_encrypt $username_password_encode 43200;   # кодируем зашифрованную basic авторизацию     set_encode_base64 $auth_encode $auth_encrypt;   # помещаем зашифрованную basic авторизацию в авторизационную куку на 12 часов     add_header Set-Cookie "Auth=$auth_encode; Max-Age=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; } location =/grant {     internal; # запрос только для внутреннего использования   # задаём и кодируем хост     set_escape_uri $host_escape $host;   # запрещаем сжимать ответ     proxy_set_header Accept-Encoding deflate;   # перенаправляем запрос на дополнительный локальный сервер     proxy_pass http://localhost/grant?request_uri=$arg_request_uri&code=$arg_code&host=$host_escape; }

Для получения гранта используем дополнительный локальный сервер

server {     listen localhost; # слушаем локально     allow 127.0.0.1; # разрешаем только локальные подключения     deny all; # и запрещаем все остальные     location =/grant {         evaluate $token @token; # получаем токен         json_loads $token_json $token; # загружаем его         json_dumps $id_token $token_json id_token; # извлекаем идентификационный токен         auth_jwt $id_token; # задаём его в качестве jwt         auth_jwt_alg RS256; # задаём тип токена         auth_jwt_key /path/to/our/pub.key file; # задаём наш публичный ключ         echo -n $jwt_grant; # отдаём тело токена     }     location @token {   # задаём домен нашего приложения на auth0     set $domain our.application.domain.com;   # задаём и кодируем идентификатор нашего приложения на auth0     set_escape_uri $client_id_escape YourApplicationClientID;   # задаём и кодируем пароль нашего приложения на auth0     set_escape_uri $client_secret_escape YourApplicationClientSecret;     # задаём и кодируем тип авторизации         set_escape_uri $grant_type_escape authorization_code;     # раскодируем хост         set_unescape_uri $host_unescape $arg_host;     # задаём и кодируем адрес возврата         set_escape_uri $redirect_uri_escape https://$host_unescape/login?request_uri=$arg_request_uri; # задаём метод запроса             proxy_method POST;     # задаём тело запроса         proxy_set_body client_id=$client_id_escape&code=$arg_code&redirect_uri=$redirect_uri_escape&client_secret=$client_secret_escape&grant_type=$grant_type_escape;     # запрещаем сжимать ответ         proxy_set_header Accept-Encoding deflate;     # задаём тип тела запроса         proxy_set_header Content-Type application/x-www-form-urlencoded;     # разрешаем перелавать имя сервера         proxy_ssl_server_name on;     # перенаправляем запрос на auth0         proxy_pass https://$domain/oauth/token;   } }


ссылка на оригинал статьи https://habr.com/ru/post/650911/