Для приготовления авторизации через 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;
}
}