Перейти к содержанию

phantom-token: Модуль Phantom Token для NGINX

Установка

Вы можете установить этот модуль в любой дистрибутив на базе RHEL, включая, но не ограничиваясь:

  • RedHat Enterprise Linux 7, 8, 9 и 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 и Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-phantom-token
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-phantom-token

Включите модуль, добавив следующее в начало файла /etc/nginx/nginx.conf:

load_module modules/ngx_curity_http_phantom_token_module.so;

Этот документ описывает nginx-module-phantom-token v2.0.0, выпущенный 22 мая 2025 года.


Quality Availability

Модуль NGINX, который анализирует токены доступа в соответствии с RFC 7662, создавая "фантомный токен", который может быть передан на бэкенд API и веб-сервисы. Узнайте больше о подходе Phantom Token.

Этот модуль, когда он включен, фильтрует входящие запросы, отказывая в доступе тем, у кого нет действительного токена доступа OAuth, представленного в заголовке Authorization. Из этого заголовка извлекается access_token и анализируется с использованием настроенной конечной точки. Curity Identity Server отвечает на этот запрос в соответствии со стандартом. Для активного токена доступа тело ответа Curity Identity Server содержит JWT, который заменяет токен доступа в заголовке запроса, который NGINX передает на бэкенд. Если токен недействителен или отсутствует, запрос на бэкенд не выполняется, и вызывающему возвращается ошибка 401, несанкционированный доступ. Этот поток показан на следующей диаграмме:

NGINX / Curity integration

Начальные вызовы приложения (веб или нативного) выполняются с использованием OpenID Connect (OIDC). Важно, что выданный токен является непрозрачным токеном доступа. Это GUID или UUID или несколько случайных байтов; в этом токене нет данных, связанных с личностью. Это фантом фактических пользовательских данных, отсюда и название -- фантомный токен. Приложение представляет токен шлюзу NGINX в соответствии со спецификацией Bearer Token Usage (т.е. RFC 6750). Этот стандарт говорит о том, что приложение должно отправить фантомный токен в заголовке запроса Authorization.

Как только сервер NGINX получает токен доступа, этот модуль вступает в действие. Используя конфигурацию, подобную приведенной ниже, этот модуль будет опрашивать запрос, находить токен и делать боковой вызов к Curity Identity Server. Этот запрос веб-сервиса будет выполнен с использованием стандарта Token Introspection (RFC 7662) с типом Accept равным application/jwt (как определено в RFC 7519). Это заставит Curity Identity Server вернуть не JSON, а просто JWT. Затем модуль передаст токен JWT на бэкенд API и микросервисы.

Если модуль также настроен для кэширования результатов вызова к Curity Identity Server (что должно быть сделано для производственных случаев), фантомный токен будет использоваться в качестве ключа кэша для соответствующего токена JWT. Это устранит необходимость в последующих вызовах к Curity Identity Server на время, пока он сообщает модулю NGINX, что может кэшировать JWT.

Кратко говоря, это очень простой API-шлюз, который работает очень быстро, высоко масштабируем и не имеет лишних функций, которые могут помешать. Весь код здесь, поэтому его легко изменить и использовать с другими OAuth-серверами!

Директивы конфигурации модуля

Версия 2.0 представила СУЩЕСТВЕННОЕ ИЗМЕНЕНИЕ для использования обновленных директив конфигурации.\ Смотрите предыдущие инструкции по конфигурации для настройки более ранних версий.

Обязательные директивы конфигурации

Директивы в этом подразделе обязательны; если какая-либо из них пропущена, модуль будет отключен.

phantom_token

Синтаксис: phantom_token on | off

По умолчанию: off

Контекст: location

phantom_token_introspection_endpoint

Синтаксис: phantom_token_introspection_endpoint string

По умолчанию:

Контекст: location

Необязательные директивы конфигурации

Следующие директивы являются необязательными и не требуют настройки.

phantom_token_realm

Синтаксис: phantom_token_realm string

По умолчанию: api

Контекст: location

Имя защищенной области или сферы защиты, которая должна использоваться, когда клиент не предоставляет токен доступа.

Пример конфигурации:

location / {
   ...
   phantom_token_realm "myGoodRealm";
}   

phantom_token_scopes

Синтаксис: phantom_token_scopes string

По умолчанию:

Контекст: location

Список областей, разделенных пробелами, которые сервер должен сообщить клиенту как обязательные, когда он не предоставляет токен доступа.

Пример конфигурации:

location / {
   ...
   phantom_token_scopes "scope_a scope_b scope_c";
}

phantom_token_scope

Синтаксис: phantom_token_scope string

По умолчанию:

Контекст: location

Массив областей, которые сервер должен сообщить клиенту как обязательные, когда он не предоставляет токен доступа. Если phantom_token_scopes также настроен, это значение будет иметь приоритет.

Пример конфигурации:

location / {
   ...
   phantom_token_scope "scope_a";
   phantom_token_scope "scope_b";
   phantom_token_scope "scope_c";
}

Пример конфигурации

Загрузка модуля

Если модуль загружен с GitHub или скомпилирован как динамическая библиотека (по умолчанию) и не был явно скомпилирован в NGINX, его необходимо загрузить с помощью директивы load_module. Это нужно сделать в главной части конфигурации NGINX:

load_module modules/ngx_curity_http_phantom_token_module.so;

Файл может быть абсолютным или относительным путем. Если он не абсолютный, он должен быть относительным к корневому каталогу NGINX.

Параметры NGINX для конечной точки анализа

Вы также должны настроить следующие параметры NGINX для подзапроса анализа:

location curity {
    internal;
    proxy_pass_request_headers off;
    proxy_set_header Accept "application/jwt";
    proxy_set_header Content-Type "application/x-www-form-urlencoded";
    proxy_set_header Authorization "Basic bXlfY2xpZW50X2lkOm15X2NsaWVudF9zZWNyZXQ=";
    proxy_pass "https://curity.example.com/oauth/v2/oauth-introspect";
}
Настройка анализа Описание
internal Запретить внешнюю доступность конечной точки анализа.
proxy_pass_request_headers Установить в off, чтобы избежать использования заголовков основного запроса в подзапросе анализа.
Accept header Настроить фиксированное значение application/jwt.
Content-Type header Настроить фиксированное значение application/x-www-form-urlencoded.
Authorization header Настроить базовую учетную запись с идентификатором клиента анализа и секретом клиента.

Чтобы получить базовую учетную запись, соедините идентификатор клиента, двоеточие и секрет клиента, затем закодируйте их в base64. Следующая команда предоставляет пример.

echo -n "my_client_id:my_client_secret" | base64

Простая конфигурация

Следующая конфигурация может быть использована в демонстрационных или разработческих средах, где обратный прокси NGINX находится на том же хосте, что и Curity Identity Server:

server {
    location /api {
        phantom_token on;
        phantom_token_introspection_endpoint curity;
        proxy_pass https://example.com/api;
    }

    location curity {
        internal;
        proxy_pass_request_headers off;
        proxy_set_header Accept "application/jwt";
        proxy_set_header Content-Type "application/x-www-form-urlencoded";
        proxy_set_header Authorization "Basic bXlfY2xpZW50X2lkOm15X2NsaWVudF9zZWNyZXQ=";
        proxy_pass "https://curity.example.com/oauth/v2/oauth-introspect";
    }
}

Сложная конфигурация

Следующая конфигурация более сложная, где обратный прокси NGINX находится на отдельном хосте от Curity Identity Server:

server {
    server_name server1.example.com;
    location /api {
        phantom_token on;
        phantom_token_introspection_endpoint curity;
        phantom_token_realm "myGoodAPI";
        phantom_token_scopes "scope_a scope_b scope_c";
        proxy_pass https://example.com/api;
    }

    location curity {
        internal;
        proxy_pass_request_headers off;
        proxy_set_header Accept "application/jwt";
        proxy_set_header Content-Type "application/x-www-form-urlencoded";
        proxy_set_header Authorization "Basic bXlfY2xpZW50X2lkOm15X2NsaWVudF9zZWNyZXQ=";
        proxy_pass "https://server2.example.com:8443/oauth/v2/oauth-introspect";
    }
}

server {
    listen 8443;
    server_name server2.example.com;
    location / {
        proxy_pass "https://curity.example.com";
    }
}

Более продвинутая конфигурация с отдельными серверами и кэшированием

Этот модуль использует встроенную директиву NGINX proxy_cache. Чтобы иметь возможность кэшировать запросы, сделанные к конечной точке анализа, кроме proxy_cache_path в контексте http и proxy_cache в контексте location, вам нужно добавить следующие 3 директивы в контекст location конечной точки анализа.

  • proxy_cache_methods POST; POST-запросы по умолчанию не кэшируются.
  • proxy_cache_key $request_body; Ключ кэша связан с access_token, отправленным в оригинальном запросе. Разные запросы с одним и тем же access_token достигают одного и того же кэша.
  • proxy_ignore_headers Set-Cookie; NGINX не будет кэшировать ответ, если заголовок Set-Cookie не игнорируется.
http {
    proxy_cache_path /path/to/cache/cache levels=1:2 keys_zone=my_cache:10m max_size=10g
                     inactive=60m use_temp_path=off;
    server {
        server_name server1.example.com;
        location /api {
            phantom_token on;
            phantom_token_introspection_endpoint curity;
            phantom_token_scopes "scope_a scope_b scope_c";
            phantom_token_realm "myGoodAPI";
            proxy_pass https://example.com/api;
        }

        location curity {
            internal;            
            proxy_pass_request_headers off;
            proxy_set_header Accept "application/jwt";
            proxy_set_header Content-Type "application/x-www-form-urlencoded";
            proxy_set_header Authorization "Basic bXlfY2xpZW50X2lkOm15X2NsaWVudF9zZWNyZXQ=";

            proxy_cache_methods POST;
            proxy_cache my_cache;
            proxy_cache_key $request_body;
            proxy_ignore_headers Set-Cookie;

            proxy_pass "https://server2.example.com:8443/oauth/v2/oauth-introspect";
        }
    }

    server {
        listen 8443;
        server_name server2.example.com;
        location / {
            proxy_pass "https://curity.example.com";
        }
    }
}   

Конфигурация без кэширования

Рекомендуется кэшировать результаты вызова к Curity Identity Server, чтобы избежать триггера запроса на анализ для каждого API-запроса. Если вы хотите отключить кэширование, вам следует увеличить значение по умолчанию для proxy_buffer_size, чтобы гарантировать, что модуль может читать большие JWT. Сделайте это, обновив конфигурацию запроса на анализ, как в следующем примере.

http {
    server {
        server_name server1.example.com;
        location /api {
            phantom_token on;
            phantom_token_introspection_endpoint curity;
            phantom_token_scopes "scope_a scope_b scope_c";
            phantom_token_realm "myGoodAPI";
            proxy_pass https://example.com/api;
        }

        location curity {
            internal;
            proxy_pass_request_headers off;
            proxy_set_header Accept "application/jwt";
            proxy_set_header Content-Type "application/x-www-form-urlencoded";
            proxy_set_header Authorization "Basic bXlfY2xpZW50X2lkOm15X2NsaWVudF9zZWNyZXQ=";

            proxy_ignore_headers Set-Cookie;
            proxy_buffer_size 16k;
            proxy_buffers 4 16k;

            proxy_pass "https://server2.example.com:8443/oauth/v2/oauth-introspect";
        }
    }

    server {
        listen 8443;
        server_name server2.example.com;
        location / {
            proxy_pass "https://curity.example.com";
        }
    }
}   

Дополнительная информация

Для получения дополнительной информации о Curity Identity Server, его возможностях и о том, как использовать его для выдачи фантомных токенов для микросервисов, посетите curity.io. Для получения справочной информации о том, как использовать Curity Identity Server для защиты доступа к API, смотрите наши ресурсы по безопасности API.

GitHub

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-phantom-token.