Для приготовления авторизации через 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
Далее, в конфиге
# отключаем авторизационный заголовок more_clear_input_headers Authorization; # задаём домен нашего приложения на 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;
Теперь защищаем всё авторизацией
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; } # подменяем авторизацию на basic (чтобы использовать переменную $remote_user) more_set_input_headers "Authorization: Basic $auth_decrypt"; echo -n OK; # пользователь авторизован }
Для авторизованных пользователей
location / { alias html/$remote_user/; # показываем контент из их папки }
А при отсутствии авторизации
error_page 401 = @auth; location @auth { # задаём и кодируем скоупы set_escape_uri $scope_escape "openid profile"; # перенаправляем клиента на auth0 return 303 https://$domain/authorize?client_id=$client_id_escape&redirect_uri=$redirect_uri_escape&response_type=code&scope=$scope_escape&state=0; }
После успешной авторизации пользователя в auth0, его перенаправляет на заданный адрес возврата
location =/login { auth_request off; # не используем авторизацию 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; # задаём наш публичный ключ # и переходим к дальнейшей обработке redirect /continue?name=$jwt_grant_name&request_uri=$arg_request_uri; } location =/continue { auth_request off; # не используем авторизацию internal; # только для внутреннего использования # если имя не получено, то значит пользователь не авторизован if ($arg_name = "") { return 401 UNAUTHORIZED; } # задаём случайный пароль для basic авторизации set_secure_random_alphanum $password 8; # задаём и кодируем basic авторизацию set_encode_base64 $username_password_encode $arg_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 =/token { internal; # только для внутреннего использования # задаём и кодируем пароль нашего приложения на auth0 set_escape_uri $client_secret_escape YourApplicationClientSecret; # задаём метод запроса 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=authorization_code; # запрещаем сжимать ответ 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; }
