Many APIs sit behind a reverse proxy that terminates TLS and routes traffic, and teams then have to decide whether that proxy is enough or whether they also need an API gateway. An API gateway is technically a reverse proxy, so the real question is which controls you need at the edge: TLS and routing, or also caller authentication, token validation, per-consumer quotas and schema checks. This guide compares the two roles by layer of enforcement, explains where token validation should live, covers how API keys and other non-human credentials are handled, and lists the bypass patterns that defeat both. It is for platform, API and security engineers who already run a reverse proxy in front of APIs and need to decide what to add, and where.
Key takeaways
- The difference is what the layer knows. A reverse proxy knows hosts, paths and connections; an API gateway also knows the API, the consumer and the plan, so it can authenticate callers and meter them.
- A configured proxy can become a gateway. Proxies such as Envoy and NGINX can validate JWTs, call an external authoriser and rate limit, but each added function is code you now own as a gateway.
- Rate limiting per IP is not quota per consumer. Proxy limits keyed on client address cannot tell one partner from another behind the same NAT, or one stolen API key spread across many addresses.
- Edge validation never replaces service checks. Validate tokens early at the edge, and still validate audience and authorise objects in the service, because anything that reaches the service another way skips the edge.
- Bypass is the main failure. If backends accept traffic that did not pass through the gateway, or trust identity headers anyone can set, the edge controls are decorative.
What each one is
A reverse proxy accepts client connections on behalf of backend servers. Its core jobs are TLS termination, routing by host and path, load balancing, connection and request limits, header normalisation and caching. It is the right place for transport and protocol hygiene. The Proxies and Forward vs Reverse Proxy Security Guide covers hardening those functions, including client IP handling and request smuggling, and is not repeated here.
An API gateway is a reverse proxy specialised for APIs. On top of proxying it holds an API catalogue (routes, versions, often an OpenAPI definition), a consumer registry (applications, API keys, OAuth clients, certificates), and policies attached to both: authentication, scopes per route, quotas and rate limits per consumer or plan, request and response transformation, schema validation and per-consumer analytics. The API Gateway Security Guide covers securing the gateway itself.
So "is NGINX an API gateway?" has a practical answer: it is a reverse proxy that can be configured to perform gateway functions. Whether it is one in your estate depends on whether it is doing consumer-aware enforcement, and whether those functions are managed as a product with owners, tests and an inventory.
Layer of enforcement, side by side
| Function | Reverse proxy (typical) | API gateway (typical) |
|---|---|---|
| TLS termination and certificates | Primary | Primary, or delegated to the proxy in front |
| Routing | Host and path to backend pool | API, version and operation to service |
| Caller identity | Client IP, optionally client certificate | Consumer or application via API key, OAuth client, JWT or certificate |
| Token validation | Possible with modules or filters | Built-in policy per route |
| Authorisation | Path allow and deny rules | Scopes or roles per route; external policy calls |
| Rate limiting | Per IP, per server, per path | Per consumer, per plan, per operation, with quotas over days or months |
| Schema validation | Rare; body size limits only | Request validation against the API definition |
| Credential lifecycle | None | Issue, rotate and revoke keys; link to developer portal |
| Inventory | Config file of routes | Catalogue of APIs and consumers |
| Logging | Access logs by IP and path | Per-consumer, per-operation logs and analytics |
What a reverse proxy can enforce, and how far it stretches
Open source proxies can add several gateway functions. The examples below use two widely deployed proxies, listed alphabetically; the same functions exist in other products under different names.
Envoy
- JWT validation: the jwt_authn HTTP filter verifies signature, issuer, audience where configured, and expiry and not-before, using keys inline or fetched as a remote JWKS with a cache duration. Requirements are set per route match, and the first matching rule wins; a route with no matching rule or an empty requires block is not checked.
- Claims to upstream: forward_payload_header and claim_to_headers pass verified claims to the backend, and Envoy strips those configured header names from every incoming request so clients cannot spoof them.
- External authorisation: the ext_authz filter calls a gRPC or HTTP authorisation service and returns 403 for denied requests. The failure_mode_allow setting decides whether requests pass when the authoriser errors; set it to false for protected routes.
- Unsafe mode to avoid: extract_only_without_validation reads claims without verifying the signature. The documentation flags it as unsafe for authorisation.
NGINX
- JWT validation: the auth_jwt module validates signed (and encrypted or nested) JWTs against a JWK Set from a file or subrequest, with auth_jwt_require for claim checks such as issuer or audience. The module is part of the commercial subscription, not open source nginx.
- Delegated authentication: auth_request sends a subrequest to an authentication service: 2xx allows, 401 or 403 denies, anything else is an error. It is not built by default and needs the --with-http_auth_request_module build option.
- Rate limiting: limit_req uses a leaky bucket keyed on any variable, commonly $binary_remote_addr. The default rejection status is 503; set limit_req_status 429 for APIs. limit_req_dry_run on counts excess requests without limiting them, which is useful while you size limits.
Where the stretch ends: the proxy can check a token, but it has no consumer registry, so per-consumer quotas, key issuance and revocation, plan management and a catalogue of who uses which API must be built and maintained separately. Once you are writing that glue, you are running a home-grown gateway, and it needs the same ownership, testing and change control as a product.
Where token validation should live
Token placement is the core design decision. The OWASP Microservices Security Cheat Sheet puts it plainly: use gateway checks to reject unauthorised ingress and prevent direct access that bypasses them, keep fine-grained authorisation in the service, and remember that gateway checks do not establish that a downstream operation is authorised.
| Check | Edge (proxy or gateway) | Service |
|---|---|---|
| Token present and well formed | Yes, reject early | Yes, defensively |
| Signature, algorithm allowlist, issuer, expiry | Yes | Yes, or trust a re-minted internal token |
| Audience | Check the API's audience | Check its own audience to stop internal replay |
| Scope or role for the route | Coarse check | Fine check per operation |
| Object, tenant and field access | No | Yes, always (OWASP API1 and API3) |
| Revocation before expiry | Introspection or short lifetimes | Same; local validation alone will not see revocation |
The edge is the right place to stop unauthenticated and malformed traffic cheaply, and to give one consistent validator for issuer, algorithm and key rotation. It is the wrong place to be the only check. See API Gateway vs In-Service Token Validation for the full placement analysis and the JWT Security Guide for the checks themselves.
API keys and other non-human credentials
Most API callers are workloads, partners and agents, not people. That makes the credential lifecycle a gateway question more than a proxy one.
- API keys: a proxy can compare a header against a static list, but that list has no owner, expiry or usage record. A gateway issues keys per consumer, ties them to a plan, logs per-key usage and supports rotation and revocation. Treat each key as a non-human identity with an owner. See the API Key Management Guide.
- OAuth clients and JWTs: prefer short-lived access tokens from an authorisation server over long-lived keys for machine callers; the edge validates them, the gateway maps client IDs to consumers for quotas.
- Mutual TLS: either layer can require client certificates; a gateway can map the certificate subject to a consumer. See the mTLS Guide.
- The edge's own credentials: the proxy or gateway holds TLS private keys, JWKS or introspection client secrets, backend credentials and admin API tokens. Store them in a secrets manager, scope them narrowly and rotate them; a stolen gateway admin token rewrites every policy at once.
- Never put keys in URLs: query string credentials end up in proxy access logs, analytics and browser history. Accept credentials only in headers and mask them in logs.
Decision guidance: proxy only, gateway, or both
| Situation | Recommended pattern |
|---|---|
| A few internal APIs, one team, callers all use the same identity provider | Reverse proxy with JWT validation and IP-based limits; services authorise |
| Public or partner APIs with many consumers, plans or billing | API gateway behind the edge proxy or load balancer |
| Need per-consumer quotas, key issuance, developer portal | API gateway |
| Already behind a cloud load balancer or CDN that terminates TLS | Keep TLS and DDoS at the edge; add a gateway only for consumer-aware controls |
| Microservices with heavy east-west traffic | Gateway for north-south, mesh or in-service validation for east-west |
| Strict latency budget | Validate JWTs locally at one layer with cached keys; avoid chained introspection calls |
"Do I need an API gateway behind a load balancer?" depends on the consumer questions, not the network ones. A load balancer or reverse proxy answers "where does this request go?". You need a gateway when you also must answer "which customer or workload is this, what plan are they on, and how much have they used?". Small organisations can usually start with a well-configured proxy plus service-side authorisation, and move to a gateway when the number of external consumers or the need for quotas makes per-IP controls unworkable. Large organisations usually end up with layers: CDN or WAF, edge proxy or load balancer, gateway, and service checks, with clear ownership of which layer enforces what. See WAF vs API Gateway and API Gateway vs Service Mesh.
Worked scenario
A company exposes a partner API through an NGINX reverse proxy that terminates TLS and routes /v1/ to a service cluster. Partners send a static API key in a header, checked by a map in the proxy config, and limit_req caps each client IP at 10 requests per second. Three problems surface. One partner runs behind a shared egress range and keeps hitting the IP limit, while a leaked key is used from hundreds of cloud addresses and never trips it. Nobody can say which partner made which call, because the logs record IPs. And a new route was added to the service but not to the proxy map, and is reachable directly on the internal load balancer used by a batch job.
The fix keeps the proxy for TLS, smuggling protection and coarse limits, and inserts a gateway behind it: per-partner keys or OAuth clients with owners and expiry, quotas per consumer, per-consumer logs, and request validation against the OpenAPI definition. Backends accept traffic only from the gateway (network policy plus mutual TLS), and the service still checks token audience and object ownership.
How to implement
- Inventory: list every API route, how it is reached (proxy, load balancer, direct) and who calls it. Routes not behind the edge are the first finding.
- Assign layers: write down which layer enforces TLS, authentication, quotas, schema and authorisation for each API, and get the owners to agree.
- Close direct paths: restrict backends to accept connections only from the gateway or proxy tier, using network policy, security groups and mutual TLS.
- Add edge validation in observe mode: log token and key validation failures and limit hits (for example limit_req_dry_run) before rejecting, to find broken clients.
- Enforce by API: switch on rejection per API in rings, starting with internal consumers, with a tested rollback.
- Keep service checks: confirm each service validates audience and authorises objects, with tests that call the service directly.
- Migrate credentials: move static keys into the gateway's consumer registry with owners, expiry and rotation, then delete the proxy key list.
Detection and measurement
- Log at the edge with a request ID passed to services, including consumer ID, route, decision and reason, and correlate with service logs.
- Alert on backend requests that arrive without the gateway's request ID or from addresses outside the gateway tier: that is bypass.
- Alert on spikes of 401 and 403 by consumer, on a single key used from many addresses or countries, and on configuration changes to routes and authentication policies.
Metrics:
- Route coverage: percentage of API routes that are only reachable through the edge.
- Authenticated route share: percentage of routes with mandatory caller authentication at the edge.
- Credential hygiene: share of API keys with an owner and expiry; median key age.
- Quota coverage: percentage of external consumers with per-consumer limits.
- Bypass attempts detected per month, and time to close a newly found direct path.
Common failure patterns
- Direct backend access. Services listen on addresses reachable from other networks, so attackers skip the gateway. OWASP API9 Improper Inventory Management often starts here.
- Trusting identity headers. Backends accept X-User or X-Consumer headers set by the edge, but the edge does not strip client-supplied copies, so any caller can claim any identity.
- Fail-open authorisers. An external authorisation call configured to allow on error (failure_mode_allow true in Envoy) silently opens routes during an outage.
- Unmatched routes skip checks. Per-route JWT rules where a new path matches no rule, so no validation runs.
- Per-IP limits mistaken for quotas. Leaked keys spread across many addresses consume resources without hitting limits (API4 Unrestricted Resource Consumption).
- Edge-only authorisation. The gateway checks scopes, and the service trusts every request that reaches it, so one leaked internal path exposes all objects (API1 Broken Object Level Authorization).
Framework mapping
| Framework | Reference | Reverse proxy | API gateway |
|---|---|---|---|
| NIST SP 800-53 Rev. 5 | SC-7 Boundary Protection | Primary | Primary |
| NIST SP 800-53 Rev. 5 | IA-9 Service Identification and Authentication, AC-3 Access Enforcement | Supporting (mTLS, JWT filters) | Primary |
| NIST SP 800-53 Rev. 5 | IA-5 Authenticator Management | No | Key and client lifecycle |
| NIST SP 800-53 Rev. 5 | SC-5 Denial-of-service Protection, SI-10 Information Input Validation | Connection and rate limits | Quotas and schema validation |
| NIST CSF 2.0 | PR.AA-05, PR.IR-01, DE.CM-01 | Network protection and monitoring | Access enforcement and consumer monitoring |
| MITRE ATT&CK v20 | T1190 Exploit Public-Facing Application, T1528 Steal Application Access Token, T1110 Brute Force | Limit and log | Authenticate, meter and revoke |
NIST SP 800-228, Guidelines for API Protection for Cloud-Native Systems (final, updated 13 March 2026), compares implementation options for API controls and is the most specific NIST reference.
Practitioner checklist
- Document which layer enforces TLS, authentication, quotas, schema and authorisation for every API.
- Make backends reachable only from the gateway or proxy tier, enforced by network policy and mTLS.
- Strip client-supplied identity headers at the first hop and sign or re-mint identity passed inward.
- Configure token validation with an algorithm allowlist, issuer, audience and expiry, and a default-deny rule for unmatched routes.
- Set external authorisers to fail closed on protected routes.
- Use per-consumer quotas for external callers; return 429, not 503, for limit hits.
- Give every API key an owner, expiry and rotation, accepted only in headers and masked in logs.
- Keep object and tenant authorisation in the service, tested by calling it directly.
- Alert on traffic that reaches backends without passing through the edge.
Standards and references
- NIST: SP 800-228 Guidelines for API Protection for Cloud-Native Systems
- OWASP: API Security Top 10 2023
- OWASP: Microservices Security Cheat Sheet
- Envoy: JWT Authentication filter
- Envoy: External Authorization filter
- NGINX: Module ngx_http_auth_jwt_module
- NGINX: Module ngx_http_auth_request_module
- NGINX: Module ngx_http_limit_req_module
Related NHI Mgmt Group resources: API Gateway Security Guide · Proxies and Forward vs Reverse Proxy Security Guide · API Gateway vs In-Service Token Validation · WAF vs API Gateway · API Key Management Guide