Рецепты 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/


Интересные статьи

Интересные статьи

Сегодня поговорим за локации, а именно какими они бывают, на что должны обратить внимание игрока и какой посыл они несут. Как они подразделяются на различные виды и чт...
В прошлой части мы поговорили о советах директору по разработке бизнес-процесса в Битрикс24, сейчас же я постараюсь дать советы руководителям отделов, поскольку по моему опыту почти всегд...
В эту субботу 1 февраля 2020 г. в нашем Хакспейсе Нейрон в Москве пройдет мастер-класс по практическому использованию DMA-атак. Вместе мы будем взламывать реальный компьютер с зашифрованной фай...
Компании переполнили рынок товаров и услуг предложениями. Разнообразие наблюдается не только в офлайне, но и в интернете. Достаточно вбить в поисковик любой запрос, чтобы получить подтверждение насыще...
Битрикс24 — популярная в малом бизнесе CRM c большими возможностями даже на бесплатном тарифе. Благодаря API Битрикс24 (даже в облачной редакции) можно легко интегрировать с другими системами.