Is it considered OK to "authenticate" via unverifiable plain-string headers simply asserting a principal name (User-ID: 12345), as long as this is behind an API gateway that does verify authentication?

In addition to their basic purpose as a reverse proxy (URL-based routing, SSL termination, load balancing, etc), API gateways are often used to consolidate request authentication. See for example Kong: Authentication Reference, AWS API Gateway: Access Control.

I'm reviewing some architectures that do this, but then replace the verifiable authentication inputs with plain headers, comparable to a user name. As plain headers, these cannot be verified by any actual upstream services. In other words, the actual resource servers simply receive a plain string header to the effect of User-ID: 12345. Note that behind the API gateway communications are also in plain HTTP (SSL is terminated at the gateway).

Example: Unverifiable Headers: Official Kong OAuth 2.0 authenticator sets Upstream Headers

This makes me deeply uncomfortable, as any agent that can communicate with the resource server in the internal network behind the API gateway can simply claim to be whichever principal they want by setting the header value. The argument presented to justify this is that the resource servers are only accessible via the gateway(s), in their own virtual private networks.

My preference, to be clear, would not be to pass all authentication details back to each resource server to process in full, but for the API gateway(s) to provide a cryptographically verifiable assertion (such as a JWT with a sub claim) that only the API gateway or its delegated authenticator could produce. Resource servers would then be able to verify that the identity claim was asserted by a trusted source, not just any agent on the network who wants to be User-ID: 12345.

Example: Verifiable JWT: Official Kong OpenID Connect authenticator, specifically Headers seems to indicate that the header it sets is a verifiable JWT, though there is no description of which key is used to sign it.

By default, the plugin passes an access token in Authorization: Bearer <access-token> header to the upstream service

So, my fellow professionals, am I just stuck in the mud in a paranoid world where nothing can be trusted? Is the unverifiable header approach I've described above, which relies completely on the correct configuration of the virtual network, considered good enough these days?

1 Answer 1


It all depends on what each company considers to be enough security for them.

The stated approach of only verifying at the border may be enough. An security-in-depth approach as you prefer would clearly be better.

In addition of the risk of an evil actor present in the same network, you should consider:

  • Unintended proxy: presence of an Unintended proxy in another system in the privileged network (relatively unlikely).
  • Header injection: I might be able to inject a new User-ID: 281745 header through embedding a newline into another header (e.g. a POST parameter copied to a header).
  • Header homonyms: if the gateway sets and filters exactly User-ID, but the processing actually treats UsEr-Id: or User_ID: as being the same header. This is not as unlikely as it seems, due to how CGI interface worked. See for example this Wikipedia incident.
  • Confused proxy: if I was able to slip two requests to the backend in what the gateway considered one, I would be in control of the headers for the second one.

Whereas a stronger verification at the final backend would make much harder to perform any of those attacks (at the cost of greater complexity there).

Obviously, none of those may be an issue currently, but get inadvertently introduced later with an update to the gateway or the backend.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .