phantom-token: Module NGINX Phantom Token
Installation
Vous pouvez installer ce module dans toute distribution basée sur RHEL, y compris, mais sans s'y limiter :
- RedHat Enterprise Linux 7, 8, 9 et 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 et 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
Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :
load_module modules/ngx_curity_http_phantom_token_module.so;
Ce document décrit nginx-module-phantom-token v2.0.0 publié le 22 mai 2025.
Module NGINX qui introspecte les jetons d'accès selon RFC 7662, produisant un "jeton fantôme" qui peut être transmis aux API et services Web en arrière-plan. Lisez-en plus sur l'approche Phantom Token.
Ce module, lorsqu'il est activé, filtre les requêtes entrantes, refusant l'accès à celles qui n'ont pas de jeton d'accès OAuth valide présenté dans un en-tête Authorization. À partir de cet en-tête, le access_token est extrait et introspecté en utilisant le point de terminaison configuré. Le Curity Identity Server répond à cette demande conformément à la norme. Pour un jeton d'accès actif, le corps de la réponse du Curity Identity Server contient le JWT qui remplace le jeton d'accès dans l'en-tête de la requête qui est transmise par NGINX au back-end. Si le jeton n'est pas valide ou absent, aucune demande au back-end n'est effectuée et l'appelant reçoit une erreur 401, non autorisé. Ce flux est illustré dans le diagramme suivant :

Les appels initiaux par l'application (web ou native) sont effectués en utilisant OpenID Connect (OIDC). La partie importante est que le jeton qui est émis est un jeton d'accès opaque. C'est un GUID ou UUID ou quelques poignées d'octets aléatoires ; il n'y a pas de données liées à l'identité dans ce jeton. C'est un fantôme des données utilisateur réelles, d'où le nom -- jeton fantôme. L'application présente le jeton à la passerelle NGINX conformément à la spécification Bearer Token Usage (c'est-à-dire, RFC 6750). Cette norme stipule que l'application doit envoyer le jeton fantôme dans l'en-tête de requête Authorization.
Une fois que le serveur NGINX reçoit le jeton d'accès, ce module s'active. En utilisant une configuration comme celle ci-dessous, ce module interrogera la requête, trouvera le jeton et effectuera un appel latéral au Curity Identity Server. Cette demande de service web sera effectuée en utilisant la norme Token Introspection (RFC 7662) avec un type Accept de application/jwt (comme défini dans RFC 7519). Cela amènera le Curity Identity Server à retourner non pas du JSON mais juste un JWT. Ensuite, le module transmettra le jeton JWT aux API et microservices en arrière-plan.
Si le module est également configuré pour mettre en cache les résultats de l'appel au Curity Identity Server (ce qui devrait être le cas pour les cas de production), le jeton fantôme sera utilisé comme clé de cache pour le jeton JWT correspondant. Cela éliminera le besoin d'appels ultérieurs au Curity Identity Server tant qu'il indique au module NGINX qu'il peut mettre en cache le JWT.
Le résumé est un passerelle API très simple qui est ultra rapide, hautement évolutive, et sans aucune fioriture qui pourrait gêner. Tout le code est ici, donc il est facile de le modifier et de l'utiliser avec d'autres serveurs OAuth même !
Directives de Configuration du Module
La version 2.0 a introduit un CHANGEMENT MAJEUR pour utiliser des directives de configuration mises à jour.\ Voir les instructions de configuration précédentes pour configurer les versions antérieures.
Directives de Configuration Requises
Les directives dans cette sous-section sont requises ; si l'une d'elles est omise, le module sera désactivé.
phantom_token
Syntaxe :
phantom_tokenon|offPar défaut :
offContexte :
location
phantom_token_introspection_endpoint
Syntaxe :
phantom_token_introspection_endpointstringPar défaut :
—Contexte :
location
Directives de Configuration Optionnelles
Les directives suivantes sont optionnelles et n'ont pas besoin d'être configurées.
phantom_token_realm
Syntaxe :
phantom_token_realmstringPar défaut :
apiContexte :
location
Le nom du domaine protégé ou de la portée de protection qui doit être utilisé lorsque le client ne fournit pas de jeton d'accès.
Exemple de configuration :
location / {
...
phantom_token_realm "myGoodRealm";
}
phantom_token_scopes
Syntaxe :
phantom_token_scopesstringPar défaut :
—Contexte :
location
La liste des portées séparées par des espaces que le serveur doit informer le client comme étant requises lorsqu'il ne fournit pas de jeton d'accès.
Exemple de configuration :
location / {
...
phantom_token_scopes "scope_a scope_b scope_c";
}
phantom_token_scope
Syntaxe :
phantom_token_scopestringPar défaut :
—Contexte :
location
Un tableau de portées que le serveur doit informer le client comme étant requises lorsqu'il ne fournit pas de jeton d'accès. Si phantom_token_scopes est également configuré, cette valeur prévaudra sur celles-ci.
Exemple de configuration :
location / {
...
phantom_token_scope "scope_a";
phantom_token_scope "scope_b";
phantom_token_scope "scope_c";
}
Exemple de Configuration
Chargement du Module
Si le module est téléchargé depuis GitHub ou compilé en tant que bibliothèque partagée (la valeur par défaut) et non explicitement compilé dans NGINX, il devra être chargé en utilisant la directive load_module. Cela doit être fait dans la partie principale de la configuration NGINX :
load_module modules/ngx_curity_http_phantom_token_module.so;
Le fichier peut être un chemin absolu ou relatif. S'il n'est pas absolu, il doit être relatif au répertoire racine de NGINX.
Paramètres NGINX pour le Point de Terminaison d'Introspection
Vous devez également configurer les paramètres NGINX suivants pour la sous-requête d'introspection :
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";
}
| Paramètre d'Introspection | Description |
|---|---|
| internal | Empêche le point de terminaison d'introspection d'être accessible de l'extérieur. |
| proxy_pass_request_headers | Défini sur off pour éviter d'utiliser les en-têtes de la requête principale dans la sous-requête d'introspection. |
| Accept header | Configure une valeur fixe de application/jwt. |
| Content-Type header | Configure une valeur fixe de application/x-www-form-urlencoded. |
| Authorization header | Configure un identifiant de base avec l'ID client d'introspection et le secret client. |
Pour obtenir l'identifiant de base, concaténez l'ID client, un caractère deux-points et le secret client, puis encodez-les en base64. La commande suivante fournit un exemple.
echo -n "my_client_id:my_client_secret" | base64
Configuration Simple
Voici une configuration simple qui pourrait être utilisée dans des environnements de démonstration ou de développement où le proxy inverse NGINX est sur le même hôte que le 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";
}
}
Configuration Complexe
Voici une configuration plus complexe où le proxy inverse NGINX est sur un hôte séparé du Curity Identity Server :
server {
server_name server1.example.com;n
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";
}
}
Configuration Plus Avancée avec Serveurs Séparés et Mise en Cache
Ce module tire parti de la directive proxy_cache intégrée de NGINX. Afin de pouvoir mettre en cache les requêtes effectuées au point de terminaison d'introspection, en plus de proxy_cache_path dans le contexte http et proxy_cache dans le contexte location, vous devez ajouter les 3 directives suivantes dans le contexte location du point de terminaison d'introspection.
proxy_cache_methods POST;Les requêtes POST ne sont pas mises en cache par défaut.proxy_cache_key $request_body;La clé du cache est liée au access_token envoyé dans la requête d'origine. Différentes requêtes utilisant le même access_token atteignent le même cache.proxy_ignore_headers Set-Cookie;NGINX ne mettra pas en cache la réponse si l'en-têteSet-Cookien'est pas ignoré.
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";
}
}
}
Configuration Sans Cache
Il est recommandé de mettre en cache les résultats de l'appel au Curity Identity Server afin d'éviter de déclencher une demande d'introspection pour chaque requête API. Si vous souhaitez désactiver la mise en cache, vous devez étendre la valeur par défaut de proxy_buffer_size pour garantir que le module peut lire de grands JWT. Faites-le en mettant à jour la configuration de la requête d'introspection comme dans l'exemple suivant.
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";
}
}
}
Plus d'Informations
Pour plus d'informations sur le Curity Identity Server, ses capacités et comment l'utiliser pour émettre des jetons fantômes pour des microservices, visitez curity.io. Pour des informations de base sur l'utilisation du Curity Identity Server pour sécuriser l'accès API, consultez nos ressources de sécurité API.
GitHub
Vous pouvez trouver des conseils de configuration supplémentaires et de la documentation pour ce module dans le dépôt GitHub pour nginx-module-phantom-token.