Introducing Identity Proxy
We built a lot of public and private APIs, they all have one thing in common, authentication works with JSON Web Tokens. Meaning there is an identity provider (IDP) that can create tokens and our API just accepts any token signed by that IDP. We also think it is a good idea to tests all your APIs, in that the new version does not break anything and works as intended.
These two things, using JWT and wanting to test everything, are usually not a very good combination. As a consultant I’ve encountered that for testing they just disabled authentication on the API, or that they create several accounts in the production IDP just for testing.
Requirements
Since building and testing large scale APIs is what I enjoy doing, I played with the idea if it would be possible to use some hacking tricks that would allow us to test an API without disabling the JWT authentication. Here are some rough requirements:
- No secrets needed for testing
- JWT authentication may not be disabled
- Allow testing all the (custom) RBAC controls in place
- No install needed, but may run in a small docker container
- As fast as possible to spin up
Introducing Identity Proxy
I would like to introduce you to IdentityProxy, an open-source project that consists out of two parts. An API that can impersonate any other identity provider, and allows you to create any token you need for testing. All neatly packaged as a small docker container. And SvRooij.Testcontainers.IdentityProxy a nuget package that uses the Testcontainers SDK to provision the Identity Proxy just for that test run.
Normal JWT flow
When your dotnet api is normally configured, it will download the openid connection configuration and the signing keys. Those are then used to validate the token, without any further communication between the API and the identity provider.
Normal JWT flow (click to open)
Identity Proxy flow
With the identity proxy, you only have to change a single configuration entry, namely the JWT:Authority. This has to point to the proxy. It will then start as normal with authentication enabled, the API will download the openid connect configuration from the proxy. This will then proxy the request to the actual IDP, and only change the jwks_uri. The url for the signing keys now also points to the proxy.
If the signing keys are loaded from the proxy, it will load the original signing keys and inject an extra signing key. This extra signing key allows the proxy to create whatever token you want without the need of any secret.
Hacked JWT flow
Sample project
Want to get started quickly? Check out this sample project which shows a protected api and a xunit test project that can actually call all the endpoints and tests all features in the api, all without disabling authentication.
Identity proxy in a podcast
A few episodes back, we talked about Identity proxy in Ctrl + Alt + Azure ep. 312, which is a great technical podcast about everything Azure and security related stuff.
Conclusion
Be sure to check out Identity Proxy works and give it a go in your next project. And if you do, please let me know on LinkedIn.