{"id":22268085,"url":"https://github.com/curityio/nginx_phantom_token_module","last_synced_at":"2025-04-07T09:19:17.162Z","repository":{"id":22836587,"uuid":"97233106","full_name":"curityio/nginx_phantom_token_module","owner":"curityio","description":"NGINX module that introspects phantom access tokens according to RFC 7662","archived":false,"fork":false,"pushed_at":"2024-11-18T08:14:58.000Z","size":600,"stargazers_count":65,"open_issues_count":3,"forks_count":16,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-31T07:08:11.106Z","etag":null,"topics":["api-gateway","introspection","nginx","oauth2","phantom-token"],"latest_commit_sha":null,"homepage":"https://curity.io/resources/learn/nginx-phantom-token-module/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/curityio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-14T12:47:58.000Z","updated_at":"2025-02-17T21:47:53.000Z","dependencies_parsed_at":"2024-09-05T13:00:25.915Z","dependency_job_id":"8b2ed08d-f34c-43d5-9951-13651d28cb6e","html_url":"https://github.com/curityio/nginx_phantom_token_module","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curityio%2Fnginx_phantom_token_module","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curityio%2Fnginx_phantom_token_module/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curityio%2Fnginx_phantom_token_module/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curityio%2Fnginx_phantom_token_module/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/curityio","download_url":"https://codeload.github.com/curityio/nginx_phantom_token_module/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247622983,"owners_count":20968575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-gateway","introspection","nginx","oauth2","phantom-token"],"created_at":"2024-12-03T11:11:02.325Z","updated_at":"2025-04-07T09:19:17.141Z","avatar_url":"https://github.com/curityio.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Phantom Token NGINX Module\n\n[![Quality](https://img.shields.io/badge/quality-production-green)](https://curity.io/resources/code-examples/status/)\n[![Availability](https://img.shields.io/badge/availability-binary-blue)](https://curity.io/resources/code-examples/status/)\n\nNGINX module that introspects access tokens according to [RFC 7662](https://tools.ietf.org/html/rfc7662), producing a \"phantom token\" that can be forwarded to back-end APIs and Web services. Read more about the [Phantom Token approach](https://curity.io/resources/learn/phantom-token-pattern/).\n\nThis module, when enabled, filters incoming requests, denying access to those which do *not* have a valid OAuth access token presented in an `Authorization` header. From this header, the access_token is extracted and introspected using the configured endpoint. The Curity Identity Server replies to this request according to the standard. For an active access token, the body of the Curity Identity Server's response contains the JWT that replaces the access token in the header of the request that is forwarded by NGINX to the back-end. If the token is not valid or absent, no request to the back-end is made and the caller is given a 401, unauthorized, error. This flow is shown in the following diagram:\n\n![NGINX / Curity integration](nginx_curity_integration.png?v=2 \"Overview of how NGINX and Curity are integrated\")\n\nThe initial calls by the app (web or native) are done using [OpenID Connect](http://openid.net/specs/openid-connect-core-1_0.html) (OIDC). The important part is that the token that is issued is an opaque access token. It is a GUID or UUID or a few handfuls of random bytes; there is no identity-related data in this token. It is a _phantom_ of the actual user data, hence the name -- _phantom token_. The app presents the token to the NGINX gateway according to the _Bearer Token Usage_ specficiation (i.e., [RFC 6750](https://tools.ietf.org/html/rfc6750)). This standard says that the app should send the phantom token in the `Authorization` request header. \n\nOnce the NGINX server receives the access token, this module will kick in. Using configuration like that below, this module will interrogate the request, find the token, and make a sideways call to the Curity Identity Server. This web service request will be done using the _Token Introspection_ standard ([RFC 7662](https://tools.ietf.org/html/rfc7662)) with an `Accept` type of `application/jwt` (as defined in [RFC 7519](https://tools.ietf.org/html/rfc7519#section-10.3.1)). This will cause the Curity Identity Server to return not JSON but just a JWT. Then, the module will forward the JWT token to the back-end APIs and microservices. \n\nIf the module is also configured to cache the results of the call to the Curity Identity Server (which it should be for production cases), the phantom token will be used as a cache key for the corresponding JWT token. This will eliminate the need for subsequent calls to the Curity Identity Server for as long as it tells the NGINX module it may cache the JWT for.\n\nThe tl;dr is a very simple API gateway that is blazing fast, highly scalable, and without any bells and whistles to get in the way. All the code is here, so it's easy to change and use with other OAuth servers even!\n\n## Configuration Directives\n\n### Required Configuration Directives\n\nAll the directives in this subsection are required; if any of these are omitted, the module will be disabled.\n\n#### phantom_token\n\n\u003e **Syntax**: **`phantom_token`** `on` | `off`\n\u003e\n\u003e **Default**: *`off`*\n\u003e\n\u003e **Context**: `location`\n\n#### phantom_token_client_credential\n\n\u003e **Syntax**: **`phantom_token_client_credential`** _`string`_ _`string`_ \n\u003e \n\u003e **Default**: *`—`*                                                                \n\u003e \n\u003e **Context**: `location`                                                           \n \nThe client ID and secret of the OAuth client which will be used for introspection. The first argument to this directive is the client ID and the second is the secret. The maximum total length of the two arguments must be less than 255 characters. Both should be printable ASCII values; non-ASCII values _may_ work but are untested. If this directive is not configured, then the module will be disabled.\n\n#### phantom_token_introspection_endpoint\n\n\u003e **Syntax**: **`phantom_token_introspection_endpoint`** _`string`_\n\u003e\n\u003e **Default**: *`—`*\n\u003e\n\u003e **Context**: `location`\n\nThe name of the location that proxies requests to the Curity Identity Server. Note that this location needs to be in the same server as the one referring to it using this directive.\n\nExample configuration:\n\n```nginx\nserver {\n    location /api {\n        ...\n        phantom_token_introspection_endpoint my_good_location_name_for_curity;\n    }\n    \n    location my_good_location_name_for_curity {\n        ...\n    }\n}\n```\n\n### Optional Configuration Directives\n\nThe following directives are optional and do not need to be configured.\n\n#### phantom_token_realm\n\n\u003e **Syntax**: **`phantom_token_realm`** _`string`_\n\u003e \n\u003e **Default**: *`api`*\n\u003e \n\u003e **Context**: `location`\n\nThe name of the protected realm or scope of protection that should be used when a client does not provide an access token.\n\nExample configuration:\n\n```nginx\nlocation / {\n   ...\n   phantom_token_realm \"myGoodRealm\";\n}   \n```\n\n#### phantom_token_scopes\n\n\u003e **Syntax**: **`phantom_token_scopes`** _`string`_\n\u003e\n\u003e **Default**: *`—`*\n\u003e\n\u003e **Context**: `location`\n\nThe space-separated list of scopes that the server should inform the client are required when it does not provide an access token.\n\nExample configuration:\n\n```nginx\nlocation / {\n   ...\n   phantom_token_scopes \"scope_a scope_b scope_c\";\n}\n```\n\n#### phantom_token_scope\n\n\u003e **Syntax**: **`phantom_token_scope`** _`string`_\n\u003e\n\u003e **Default**: *`—`*\n\u003e\n\u003e **Context**: `location`\n\nAn array of scopes that the server should inform the client are required when it does not provide an access token. If `phantom_token_scopes` is also configured, that value will supersede these.\n \nExample configuration:\n \n```nginx\nlocation / {\n   ...\n   phantom_token_scope \"scope_a\";\n   phantom_token_scope \"scope_b\";\n   phantom_token_scope \"scope_c\";\n}\n```\n\n## Sample Configuration\n\n### Loading the Module\n\nIf the module is downloaded from GitHub or compiled as a shared library (the default) and not explicitly compiled into NGINX, it will need to be loaded using the [load_module](http://nginx.org/en/docs/ngx_core_module.html#load_module) directive. This needs to be done in the _main_ part of the NGINX configuration:\n\n```nginx\nload_module modules/ngx_curity_http_phantom_token_module.so;\n```\n\nThe file can be an absolute or relative path. If it is not absolute, it should be relative to the NGINX root directory.\n\n### Simple Configuration\n\nThe following is a simple configuration that might be used in demo or development environments where the NGINX reverse proxy is on the same host as the Curity Identity Server:\n\n```nginx\nserver {\n    location /api {\n        proxy_pass         https://example.com/api;\n\n        phantom_token on;\n        phantom_token_client_credential \"client_id\" \"client_secret\";\n        phantom_token_introspection_endpoint curity;\n    }\n    \n    location curity {\n        proxy_pass \"https://curity.example.com/oauth/v2/introspection\";\n    }\n}\n```\n\n### Complex Configuration\n\nThe following is a more complex configuration where the NGINX reverse proxy is on a separate host to the Curity Identity Server:\n\n```nginx\nserver {\n    server_name server1.example.com;n\n    location /api {\n        proxy_pass         https://example.com/api;\n\n        phantom_token on;\n        phantom_token_client_credential \"client_id\" \"client_secret\";\n        phantom_token_introspection_endpoint curity;\n        \n        phantom_token_realm \"myGoodAPI\";\n        phantom_token_scopes \"scope_a scope_b scope_c\";\n    }\n    \n    location curity {\n        proxy_pass \"https://server2.example.com:8443/oauth/v2/introspection\";\n    }\n}\n\nserver {\n    listen 8443;\n    server_name server2.example.com;\n    location / {\n        proxy_pass \"https://curity.example.com\";\n    }\n}\n```\n        \n### More Advanced Configuration with Separate Servers and Caching\n\nThis module takes advantage of NGINX built-in _proxy_cache_ directive. In order to be able to cache the requests made to the introspection endpoint, except of the `proxy_cache_path` in http context and `proxy_cache` in location context, you have to add the following 3 directives in the location context of the introspection endpoint.\n\n- `proxy_cache_methods POST;` POST requests are not cached by default.\n- `proxy_cache_key $request_body;` The key of the cache is related to the _access_token_ sent in the original request. Different requests using the same _access_token_ reach the same cache.\n- `proxy_ignore_headers Set-Cookie;` NGINX will not cache the response if `Set-Cookie` header is not ignored.\n\n```nginx\nhttp {\n    proxy_cache_path /path/to/cache/cache levels=1:2 keys_zone=my_cache:10m max_size=10g\n                     inactive=60m use_temp_path=off;\n    server {\n        server_name server1.example.com;\n        location /api {\n            proxy_pass         https://example.com/api;\n\n            phantom_token on;\n            phantom_token_client_credential \"client_id\" \"client_secret\";\n            phantom_token_introspection_endpoint curity;\n            phantom_token_scopes \"scope_a scope_b scope_c\";\n            phantom_token_realm \"myGoodAPI\";\n        }\n        \n        location curity {\n            proxy_pass \"https://server2.example.com:8443/oauth/v2/introspection\";\n            \n            proxy_cache_methods POST;\n            proxy_cache my_cache;\n            proxy_cache_key $request_body;\n            proxy_ignore_headers Set-Cookie;\n        }\n    }\n    \n    server {\n        listen 8443;\n        server_name server2.example.com;\n        location / {\n            proxy_pass \"https://curity.example.com\";\n        }\n    }\n}   \n```\n\n## Cacheless Configuration\n\nIt is recommended to cache the results of the call to the Curity Identity Server so that you avoid triggering an introspection request for every API request. If you wish to disable caching you should extend the default [proxy_buffer_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#directives) to ensure that the module can read large JWTs. Do so by updating the configuration of the introspection request as in the following example.\n\n```nginx\nhttp {\n    server {\n        server_name server1.example.com;\n        location /api {\n            proxy_pass         https://example.com/api;\n\n            phantom_token on;\n            phantom_token_client_credential \"client_id\" \"client_secret\";\n            phantom_token_introspection_endpoint curity;\n            phantom_token_scopes \"scope_a scope_b scope_c\";\n            phantom_token_realm \"myGoodAPI\";\n        }\n        \n        location curity {\n            proxy_pass \"https://server2.example.com:8443/oauth/v2/introspection\";\n            proxy_ignore_headers Set-Cookie;\n            proxy_buffer_size 16k;\n            proxy_buffers 4 16k;\n        }\n    }\n    \n    server {\n        listen 8443;\n        server_name server2.example.com;\n        location / {\n            proxy_pass \"https://curity.example.com\";\n        }\n    }\n}   \n```\n\n## Compatibility\n\nThis module is compatible with Curity Identity Server versions \u003e= 2.2. It has been tested with NGINX 1.13.7 (NGINX Plus Release 14) and NGINX 1.13.10 (NGINX Plus Release 15). It is likely to work with other, newish versions of NGINX, but only these have been tested, pre-built and verified.\n\n### Releases\n\nPre-built binaries of this module are provided for the following versions of NGINX on the corresponding operating system distributions:\n\n|                                    | NGINX 1.25.5 / NGINX Plus R32 | NGINX 1.25.3 / NGINX Plus R31 | NGINX 1.25.1 / NGINX Plus R30 | NGINX 1.23.4 / NGINX Plus R29 | NGINX 1.23.2 / NGINX Plus R28 |\n| -----------------------------------|:-----------------------------:|:-----------------------------:|:-----------------------------:|:------------------------------:|:-----------------------------:|\n| Alpine                             | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/alpine.ngx_curity_http_phantom_token_module_1.25.5.so)          | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/alpine.ngx_curity_http_phantom_token_module_1.25.3.so)          | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/alpine.ngx_curity_http_phantom_token_module_1.25.1.so)          | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/alpine.ngx_curity_http_phantom_token_module_1.23.4.so)          | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/alpine.ngx_curity_http_phantom_token_module_1.23.2.so)          |\n| Debian 11.0 (Bullseye)             | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bullseye.ngx_curity_http_phantom_token_module_1.25.5.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bullseye.ngx_curity_http_phantom_token_module_1.25.3.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bullseye.ngx_curity_http_phantom_token_module_1.25.1.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bullseye.ngx_curity_http_phantom_token_module_1.23.4.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bullseye.ngx_curity_http_phantom_token_module_1.23.2.so) |\n| Debian 12.0 (Bookworm)             | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bookworm.ngx_curity_http_phantom_token_module_1.25.5.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bookworm.ngx_curity_http_phantom_token_module_1.25.3.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/debian.bookworm.ngx_curity_http_phantom_token_module_1.25.1.so) | X | X |\n| Ubuntu 20.04 LTS (Focal Fossa)     | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.20.04.ngx_curity_http_phantom_token_module_1.25.5.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.20.04.ngx_curity_http_phantom_token_module_1.25.3.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.20.04.ngx_curity_http_phantom_token_module_1.25.1.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.20.04.ngx_curity_http_phantom_token_module_1.23.4.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.20.04.ngx_curity_http_phantom_token_module_1.23.2.so)    |\n| Ubuntu 22.04 LTS (Jammy Jellyfish) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.22.04.ngx_curity_http_phantom_token_module_1.25.5.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.22.04.ngx_curity_http_phantom_token_module_1.25.3.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.22.04.ngx_curity_http_phantom_token_module_1.25.1.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.22.04.ngx_curity_http_phantom_token_module_1.23.4.so)    | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.22.04.ngx_curity_http_phantom_token_module_1.23.2.so)    |\n| Ubuntu 24.04 LTS (Noble Numbat) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/ubuntu.24.04.ngx_curity_http_phantom_token_module_1.25.5.so)    | X | X | X | X |\n| Amazon Linux 2                     | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2.ngx_curity_http_phantom_token_module_1.25.5.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2.ngx_curity_http_phantom_token_module_1.25.3.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2.ngx_curity_http_phantom_token_module_1.25.1.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2.ngx_curity_http_phantom_token_module_1.23.4.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2.ngx_curity_http_phantom_token_module_1.23.2.so)           |\n| Amazon Linux 2023                  | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2023.ngx_curity_http_phantom_token_module_1.25.5.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2023.ngx_curity_http_phantom_token_module_1.25.3.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2023.ngx_curity_http_phantom_token_module_1.25.1.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2023.ngx_curity_http_phantom_token_module_1.23.4.so)           | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/amzn2023.ngx_curity_http_phantom_token_module_1.23.2.so)           |\n| CentOS Stream 9.0+                 | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/centos.stream.9.ngx_curity_http_phantom_token_module_1.25.5.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/centos.stream.9.ngx_curity_http_phantom_token_module_1.25.3.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/centos.stream.9.ngx_curity_http_phantom_token_module_1.25.1.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/centos.stream.9.ngx_curity_http_phantom_token_module_1.23.4.so) | [⇓](https://github.com/curityio/nginx_phantom_token_module/releases/download/1.6.0/centos.stream.9.ngx_curity_http_phantom_token_module_1.23.2.so) |\n\n## Status\nThis module is fit for production usage. \n\n## Development Setup\nIf you wish to build this module from source, in order to run against other NGINX versions, or to change the module's logic, see the [Development Wiki](https://github.com/curityio/nginx_phantom_token_module/wiki) for instructions.\n\n## More Information\nFor more information about the Curity Identity Server, its capabilities, and how to use it to issue phantom tokens for microservices, visit [curity.io](https://curity.io/product/token-service/?=use-cases?tab=microservices). For background information on using the Curity Identity Server to secure API access, see our [API security resources](https://curity.io/resources/api-security).\n\n## Licensing\nThis software is copyright (C) 2022 Curity AB. It is open source software that is licensed under the [Apache v. 2](LICENSE). For commercial support of this module, please contact [Curity sales](mailto:sales@curity.io).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcurityio%2Fnginx_phantom_token_module","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcurityio%2Fnginx_phantom_token_module","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcurityio%2Fnginx_phantom_token_module/lists"}