phantom-token: Phantom Token NGINX Modul
Installation
Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:
- RedHat Enterprise Linux 7, 8, 9 und 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 und 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
Aktivieren Sie das Modul, indem Sie Folgendes an den Anfang von /etc/nginx/nginx.conf hinzufügen:
load_module modules/ngx_curity_http_phantom_token_module.so;
Dieses Dokument beschreibt nginx-module-phantom-token v2.0.0 veröffentlicht am 22. Mai 2025.
NGINX Modul, das Zugriffstoken gemäß RFC 7662 untersucht und ein "Phantom-Token" erzeugt, das an Backend-APIs und Webdienste weitergeleitet werden kann. Lesen Sie mehr über den Phantom Token Ansatz.
Dieses Modul filtert, wenn es aktiviert ist, eingehende Anfragen und verweigert den Zugriff auf diejenigen, die kein gültiges OAuth-Zugriffstoken im Authorization-Header vorlegen. Aus diesem Header wird das access_token extrahiert und unter Verwendung des konfigurierten Endpunkts untersucht. Der Curity Identity Server antwortet auf diese Anfrage gemäß dem Standard. Bei einem aktiven Zugriffstoken enthält der Body der Antwort des Curity Identity Servers das JWT, das das Zugriffstoken im Header der Anfrage ersetzt, die von NGINX an das Backend weitergeleitet wird. Wenn das Token ungültig oder nicht vorhanden ist, wird keine Anfrage an das Backend gestellt und der Anrufer erhält einen 401, nicht autorisiert, Fehler. Dieser Ablauf wird im folgenden Diagramm dargestellt:

Die ursprünglichen Aufrufe der App (Web oder nativ) erfolgen unter Verwendung von OpenID Connect (OIDC). Der wichtige Teil ist, dass das ausgegebene Token ein undurchsichtiges Zugriffstoken ist. Es handelt sich um eine GUID oder UUID oder einige Handvoll zufälliger Bytes; es gibt keine identitätsbezogenen Daten in diesem Token. Es ist ein Phantom der tatsächlichen Benutzerdaten, daher der Name -- Phantom-Token. Die App präsentiert das Token dem NGINX-Gateway gemäß der Bearer Token Usage Spezifikation (d.h. RFC 6750). Dieser Standard besagt, dass die App das Phantom-Token im Authorization-Anforderungsheader senden sollte.
Sobald der NGINX-Server das Zugriffstoken erhält, wird dieses Modul aktiv. Mit einer Konfiguration wie der folgenden wird dieses Modul die Anfrage untersuchen, das Token finden und einen seitlichen Aufruf an den Curity Identity Server durchführen. Diese Webdienstanfrage erfolgt unter Verwendung des Token Introspection Standards (RFC 7662) mit einem Accept-Typ von application/jwt (wie in RFC 7519 definiert). Dies führt dazu, dass der Curity Identity Server nicht JSON, sondern nur ein JWT zurückgibt. Dann wird das Modul das JWT-Token an die Backend-APIs und Mikrodienste weiterleiten.
Wenn das Modul auch so konfiguriert ist, dass es die Ergebnisse des Aufrufs an den Curity Identity Server zwischenspeichert (was es für Produktionsfälle tun sollte), wird das Phantom-Token als Cache-Schlüssel für das entsprechende JWT-Token verwendet. Dies eliminiert die Notwendigkeit für nachfolgende Aufrufe an den Curity Identity Server, solange er dem NGINX-Modul mitteilt, dass es das JWT zwischenspeichern darf.
Die Kurzfassung ist ein sehr einfaches API-Gateway, das blitzschnell, hochgradig skalierbar und ohne Schnickschnack ist, der im Weg steht. Der gesamte Code ist hier, sodass es einfach ist, ihn zu ändern und auch mit anderen OAuth-Servern zu verwenden!
Modulkonfigurationsdirektiven
Version 2.0 führte eine BRECHENDE ÄNDERUNG ein, um aktualisierte Konfigurationsdirektiven zu verwenden.\ Siehe frühere Konfigurationsanweisungen, um ältere Versionen zu konfigurieren.
Erforderliche Konfigurationsdirektiven
Die Direktiven in diesem Unterabschnitt sind erforderlich; wenn eine dieser Direktiven weggelassen wird, wird das Modul deaktiviert.
phantom_token
Syntax:
phantom_tokenon|offStandard:
offKontext:
location
phantom_token_introspection_endpoint
Syntax:
phantom_token_introspection_endpointstringStandard:
—Kontext:
location
Optionale Konfigurationsdirektiven
Die folgenden Direktiven sind optional und müssen nicht konfiguriert werden.
phantom_token_realm
Syntax:
phantom_token_realmstringStandard:
apiKontext:
location
Der Name des geschützten Bereichs oder des Schutzbereichs, der verwendet werden sollte, wenn ein Client kein Zugriffstoken bereitstellt.
Beispielkonfiguration:
location / {
...
phantom_token_realm "myGoodRealm";
}
phantom_token_scopes
Syntax:
phantom_token_scopesstringStandard:
—Kontext:
location
Die durch Leerzeichen getrennte Liste von Scopes, die der Server dem Client mitteilen sollte, die erforderlich sind, wenn er kein Zugriffstoken bereitstellt.
Beispielkonfiguration:
location / {
...
phantom_token_scopes "scope_a scope_b scope_c";
}
phantom_token_scope
Syntax:
phantom_token_scopestringStandard:
—Kontext:
location
Ein Array von Scopes, die der Server dem Client mitteilen sollte, die erforderlich sind, wenn er kein Zugriffstoken bereitstellt. Wenn phantom_token_scopes ebenfalls konfiguriert ist, wird dieser Wert Vorrang vor diesen haben.
Beispielkonfiguration:
location / {
...
phantom_token_scope "scope_a";
phantom_token_scope "scope_b";
phantom_token_scope "scope_c";
}
Beispielkonfiguration
Modul laden
Wenn das Modul von GitHub heruntergeladen oder als Shared Library (die Standardoption) kompiliert und nicht explizit in NGINX kompiliert wurde, muss es mit der load_module Direktive geladen werden. Dies muss im Haupt Teil der NGINX-Konfiguration erfolgen:
load_module modules/ngx_curity_http_phantom_token_module.so;
Die Datei kann ein absoluter oder relativer Pfad sein. Wenn sie nicht absolut ist, sollte sie relativ zum NGINX-Stammverzeichnis sein.
NGINX-Parameter für den Introspektionsendpunkt
Sie müssen auch die folgenden NGINX-Parameter für die Introspektionsunteranfrage konfigurieren:
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";
}
| Introspektions-Einstellung | Beschreibung |
|---|---|
| internal | Verhindert, dass der Introspektionsendpunkt extern verfügbar ist. |
| proxy_pass_request_headers | Auf "off" setzen, um zu vermeiden, dass die Header der Hauptanfrage in der Introspektionsunteranfrage verwendet werden. |
| Accept-Header | Konfigurieren Sie einen festen Wert von application/jwt. |
| Content-Type-Header | Konfigurieren Sie einen festen Wert von application/x-www-form-urlencoded. |
| Authorization-Header | Konfigurieren Sie eine grundlegende Anmeldeinformation mit der Introspektions-Client-ID und dem Client-Geheimnis. |
Um die grundlegende Anmeldeinformation zu erhalten, verketten Sie die Client-ID, ein Doppelpunktzeichen und das Client-Geheimnis und kodieren Sie sie dann in base64. Der folgende Befehl bietet ein Beispiel.
echo -n "my_client_id:my_client_secret" | base64
Einfache Konfiguration
Die folgende ist eine einfache Konfiguration, die in Demo- oder Entwicklungsumgebungen verwendet werden könnte, in denen der NGINX-Reverse-Proxy auf demselben Host wie der Curity Identity Server läuft:
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";
}
}
Komplexe Konfiguration
Die folgende ist eine komplexere Konfiguration, bei der der NGINX-Reverse-Proxy auf einem separaten Host zum Curity Identity Server läuft:
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";
}
}
Fortgeschrittene Konfiguration mit separaten Servern und Caching
Dieses Modul nutzt die integrierte proxy_cache Direktive von NGINX. Um die Anfragen an den Introspektionsendpunkt zwischenspeichern zu können, müssen Sie neben dem proxy_cache_path im HTTP-Kontext und proxy_cache im Standortkontext die folgenden 3 Direktiven im Standortkontext des Introspektionsendpunkts hinzufügen.
proxy_cache_methods POST;POST-Anfragen werden standardmäßig nicht zwischengespeichert.proxy_cache_key $request_body;Der Schlüssel des Caches bezieht sich auf das access_token, das in der ursprünglichen Anfrage gesendet wird. Verschiedene Anfragen, die dasselbe access_token verwenden, erreichen denselben Cache.proxy_ignore_headers Set-Cookie;NGINX wird die Antwort nicht zwischenspeichern, wenn derSet-Cookie-Header nicht ignoriert wird.
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";
}
}
}
Cachelose Konfiguration
Es wird empfohlen, die Ergebnisse des Aufrufs an den Curity Identity Server zu zwischenspeichern, um zu vermeiden, dass für jede API-Anfrage eine Introspektionsanfrage ausgelöst wird. Wenn Sie das Caching deaktivieren möchten, sollten Sie die Standard- proxy_buffer_size erhöhen, um sicherzustellen, dass das Modul große JWTs lesen kann. Tun Sie dies, indem Sie die Konfiguration der Introspektionsanfrage wie im folgenden Beispiel aktualisieren.
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";
}
}
}
Weitere Informationen
Für weitere Informationen über den Curity Identity Server, seine Funktionen und wie Sie ihn verwenden können, um Phantom-Tokens für Mikrodienste auszustellen, besuchen Sie curity.io. Für Hintergrundinformationen zur Verwendung des Curity Identity Servers zur Sicherung des API-Zugriffs siehe unsere API-Sicherheitsressourcen.
GitHub
Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-phantom-token.