i log it

изучаем IT

JWT-авторизация на стороне Nginx под управлением openSUSE Leap 15.5. Часть 2: Змея в тени орла, токен в строке запроса.

- Опубликовано в Nginx

Продолжение истории про Nginx и jwt-авторизацию. На этот раз ставим другой сторонний модуль jwt-авторизации для того чтобы у Nginx появилась возможность извлекать токен не только из заголовка или куки, но также из строки запроса.

Интродукция

Модуль https://github.com/kjdev/nginx-auth-jwt похож на оригинальный модуль и умеет извлекать токен из строки запроса. Согласно документации он зависит от библиотек jansson и openssl. Значит порядок установки будет следующий:

  1. Установим jansson
  2. Установим openssl
  3. Качаем JWT-модуль
  4. Качаем Echo-модуль
  5. Качаем исходный код Nginx
  6. Компилируем Nginx с модулями и включенным debug

Установим jansson

# zypper in libjansson-devel

Проверим установку

# pkg-config --modversion jansson

Установим openssl

# zypper in libopenssl-devel

Качаем JWT и Echo модули

установим git

# zypper in git

переходим в директорию куда будем качать все исходники

# cd /usr/local/src

клонируем jwt модуль

# git clone https://github.com/kjdev/nginx-auth-jwt

клонируем Echo модуль

# git clone https://github.com/openresty/echo-nginx-module

Установим необходимые библиотеки для компиляции

# zypper in gcc
# zypper in make
# zypper in pcre-devel
# zypper in libxml2-devel
# zypper in libxslt-devel
# zypper in gd-devel

Установка Nginx

Установим коробочный Nginx

# zypper in nginx
# systemctl enable nginx
# systemctl start nginx
# systemctl status nginx

Сохраним куда-нибудь себе параметры сборки коробочного Nginx:

# nginx -V

Берем все что после configure arguments:

--prefix=/usr/ --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --lock-path=/run/nginx.lock --http-client-body-temp-path=/var/lib/nginx/tmp/ --http-proxy-temp-path=/var/lib/nginx/proxy/ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi/ --http-uwsgi-temp-path=/var/lib/nginx/uwsgi/ --http-scgi-temp-path=/var/lib/nginx/scgi/ --user=nginx --group=nginx --without-select_module --without-poll_module --with-threads --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-perl=/usr/bin/perl --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_ssl_preread_module --with-pcre --with-pcre-jit --with-cc-opt='-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -fPIC -D_GNU_SOURCE' --with-ld-opt='-Wl,-z,relro,-z,now -pie' --with-compat

Качаем исходный код Nginx:

# cd /usr/local/src
# wget https://nginx.org/download/nginx-1.21.5.tar.gz
# tar -xvf nginx-1.21.5.tar.gz
# cd /usr/local/src/nginx-1.21.5

Добавим (допишем в конец) новые параметры сборки --with-debug --add-module=/usr/local/src/echo-nginx-module --add-dynamic-module=/usr/local/src/nginx-auth-jwt к параметрам коробочного Nginx, сохраненным ранее. Выполним ./configure с нашим объединенным большим списком параметров:

# ./configure --prefix=/usr/ --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/run/nginx.pid --lock-path=/run/nginx.lock --http-client-body-temp-path=/var/lib/nginx/tmp/ --http-proxy-temp-path=/var/lib/nginx/proxy/ --http-fastcgi-temp-path=/var/lib/nginx/fastcgi/ --http-uwsgi-temp-path=/var/lib/nginx/uwsgi/ --http-scgi-temp-path=/var/lib/nginx/scgi/ --user=nginx --group=nginx --without-select_module --without-poll_module --with-threads --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-perl=/usr/bin/perl --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_realip_module --with-stream_ssl_preread_module --with-pcre --with-pcre-jit --with-cc-opt='-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -g -fPIC -D_GNU_SOURCE' --with-ld-opt='-Wl,-z,relro,-z,now -pie' --with-compat --with-debug --add-module=/usr/local/src/echo-nginx-module --add-dynamic-module=/usr/local/src/nginx-auth-jwt

Затем компилируем и устанавливаем.

# make
# make install

Активируем jwt-модуль в конфиге nginx.conf. После успешной компиляции в директории /usr/lib64/nginx/modules должен появиться файл ngx_http_auth_jwt_module.so, который необходимо подключить в файле nginx.conf с помощью директивы load_module:

load_module lib64/nginx/modules/ngx_http_auth_jwt_module.so;

Настройка firewall

Без разрешения http-трафика в правилах фаервола мы не получим ответ от Nginx и не увидим результат нашей работы. OpenSUSE использует FirewallD для управления правилами фаервола. Чтобы разрешить http-трафик, выполните следующую команду:

# firewall-cmd --permanent --add-service=http
# firewall-cmd --reload

или с помощью консольной утилиты yast в зоне public добавьте http в список allowed для этого:

# yast
  1. Перемещайте курсор с помощью tab и стрелок на клавиатуре, установите курсор на зоне public и нажмите Enter
  2. Перемещаясь таким же образом, в списке known отметьте (нажать Enter) крестиком протокол http и, если необходимо, протокол https, например: [x] http.
  3. Добавтье отмеченные протоколы в список allowed. Для этого установите курсор на Add и нажмите Enter.
  4. Установите курсор на Accept и нажмите Enter

Проверим работу Nginx

В конфигурационном файле nginx.conf создадим локацию /hello в которой echo-модуль отвечает клиенту строкой "hello!"

location /hello {
echo "hello!";
}

Перезагрузим Nginx

# systemctl restart nginx

теперь сервер должен ответить hello!

Проверим работу jwt-модуля Nginx.

Добавим в локацию /hello директивы для обработки jwt-токена:

location /hello {
auth_jwt "closed site" token=$arg_token;
auth_jwt_key_file /etc/nginx/nginx.jwt.key.json keyval;
auth_jwt_validate_exp on;
echo "hello!";
}

Добавим еще одну локацию, отдающую mp4 файлы из папки media в обмен на токен:

location ~ \.(mp3|mp4) {
auth_jwt "closed site" token=$arg_token;
auth_jwt_key_file /etc/nginx/nginx.jwt.key.json keyval;
auth_jwt_validate_exp on;
root /srv/www/htdocs/media;
}

Генерируем ключ в терминале:

 # openssl rand -hex 32
fc3ee9546f6e4bc0523f57d61859cc137aefeb8a6e2a7930b06a95c0135205a5

Согласно документации, ключ в формате keyval необходимо положить в файл, например сюда: /etc/nginx/nginx.jwt.key.json. Содержимое файла:

{"kid": "fc3ee9546f6e4bc0523f57d61859cc137aefeb8a6e2a7930b06a95c0135205a5"}

Снова перезагрузим Nginx

# systemctl restart nginx

Теперь можно проверить доступ по токену.