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?