An OAuth 2.0 token operations module for nginx.
A module that performs token validation and exchange on nginx for the API Gateway pattern. By integrating with an IdP (Identity Provider), it provides the following OAuth 2.0 operations:
- Token Introspection (RFC 7662): Dynamically validates Bearer Tokens by querying the IdP
- Token Exchange (RFC 8693): Exchanges Bearer Tokens for new tokens with reduced scope and forwards them to downstream services
Introspection and Exchange can be enabled independently, providing three operating modes:
| Mode | Introspection | Exchange | Use Case |
|---|---|---|---|
| Introspect only | o | - | When token validation alone is sufficient |
| Exchange only | - | o | When the IdP validates tokens during exchange |
| Introspect + Exchange | o | o | Full pipeline (validate then exchange) |
License: BSD-2-Clause
| Module | Validation | Characteristics |
|---|---|---|
| nginx-auth-jwt | Static (JWT signature) | Performance-focused, no IdP dependency |
| nginx-auth-oauth2-token | Dynamic (IdP query) | Immediate revocation detection, scope reduction |
- Runs in the
ACCESS_PHASE(validates/exchanges tokens beforeproxy_pass) - Asynchronous HTTP communication with IdP via
ngx_http_subrequest() - Shared memory caching for Introspection/Exchange results (with TTL management)
- Exposes Introspection claims as nginx variables
- Automatically replaces the upstream
Authorizationheader with the exchanged token - Supports loading client secrets from files
See SECURITY.md for security considerations.
- Client secrets can be loaded from files (avoids embedding in configuration)
- HTTP Basic authentication for IdP communication
- JSON response size limit (64KB)
- No negative cache (
active: falseresponses are not cached) - Cache configuration is required for production (prevents IdP overload)
See INSTALL.md for installation instructions.
http {
auth_oauth2_token_client_id "my-gateway";
auth_oauth2_token_client_secret_file /etc/nginx/secrets/client_secret;
server {
listen 443 ssl;
# Proxy to IdP introspection endpoint
location = /_introspect {
internal;
proxy_pass https://idp.example.com/oauth2/introspect;
}
location /api/ {
auth_oauth2_token_introspect on;
auth_oauth2_token_introspect_endpoint /_introspect;
proxy_set_header X-User-Sub $oauth2_token_sub;
proxy_pass http://backend;
}
}
}When the IdP validates tokens during exchange, Introspection can be omitted.
http {
auth_oauth2_token_client_id "my-gateway";
auth_oauth2_token_client_secret_file /etc/nginx/secrets/client_secret;
server {
listen 443 ssl;
# Proxy to IdP token endpoint
location = /_token {
internal;
proxy_pass https://idp.example.com/oauth2/token;
}
location /api/ {
auth_oauth2_token_exchange on;
auth_oauth2_token_token_endpoint /_token;
auth_oauth2_token_audience "backend-service";
auth_oauth2_token_scope "api:read";
proxy_pass http://backend;
}
}
}http {
auth_oauth2_token_client_id "my-gateway";
auth_oauth2_token_client_secret_file /etc/nginx/secrets/client_secret;
server {
listen 443 ssl;
location = /_introspect {
internal;
proxy_pass https://idp.example.com/oauth2/introspect;
}
location = /_token {
internal;
proxy_pass https://idp.example.com/oauth2/token;
}
location /api/ {
# Introspection
auth_oauth2_token_introspect on;
auth_oauth2_token_introspect_endpoint /_introspect;
auth_oauth2_token_introspect_cache zone=introspect:10m max_ttl=60s;
# Token Exchange
auth_oauth2_token_exchange on;
auth_oauth2_token_token_endpoint /_token;
auth_oauth2_token_audience "backend-service";
auth_oauth2_token_scope "api:read";
auth_oauth2_token_exchange_cache zone=exchange:10m max_ttl=300s;
proxy_set_header X-User-Sub $oauth2_token_sub;
proxy_pass http://backend;
}
}
}Note:
auth_oauth2_token_introspect_endpointandauth_oauth2_token_token_endpointaccept the URI of aninternallocation withproxy_passto the IdP. The module automatically sets the POST request headers (Content-Type,Authorization) and body, so no additional configuration is needed on the internal location.
See DIRECTIVES.md for details.
| Directive | Description | Context |
|---|---|---|
| auth_oauth2_token_client_id | Client ID | http |
| auth_oauth2_token_client_secret | Client secret | http |
| auth_oauth2_token_client_secret_file | Client secret file path | http |
| auth_oauth2_token_introspect | Enable/disable Introspection | http, server, location |
| auth_oauth2_token_introspect_endpoint | Introspection endpoint URI | http, server, location |
| auth_oauth2_token_introspect_cache | Introspection cache settings | http, server, location |
| auth_oauth2_token_exchange | Enable/disable Exchange | http, server, location |
| auth_oauth2_token_token_endpoint | Token endpoint URI | http, server, location |
| auth_oauth2_token_audience | Exchange target audience | http, server, location |
| auth_oauth2_token_scope | Exchange requested scope | http, server, location |
| auth_oauth2_token_exchange_cache | Exchange cache settings | http, server, location |
See DIRECTIVES.md for details.
| Variable | Description |
|---|---|
$oauth2_token_active |
Introspection result (1 or 0) |
$oauth2_token_sub |
Token subject |
$oauth2_token_scope |
Token scopes (space-separated) |
$oauth2_token_client_id |
Client ID that issued the token |
$oauth2_token_exp |
Token expiration (UNIX timestamp) |
$oauth2_token_new_token |
Exchanged new token |
$oauth2_token_new_token_type |
New token type |
This module conforms to the following standards:
- RFC 7662 - OAuth 2.0 Token Introspection: Dynamic validation of Bearer Tokens
- RFC 8693 - OAuth 2.0 Token Exchange: Exchange tokens for scope-reduced tokens
Configuration & Operations:
- INSTALL.md: Installation guide
- DIRECTIVES.md: Directives and variables reference
- SECURITY.md: Security considerations (cache settings, secret management)


