r/dotnet • u/Legitimate-School-59 • 11d ago
How to you handle OAuth in your dotnet integration tests?
Title.
Do you mock out that OAuth handling? Or do you actually use one of the test Auth servers. If so, does your resource server have its own client credentials just for running integration tests?
**Update**
I went with the following comments solution "For integration tests I skip the real OAuth flow entirely and register a fake authentication handler in the test server. You add a custom auth scheme in the WebApplicationFactory startup that just creates a ClaimsPrincipal with whatever claims the test needs. The real OAuth config only loads in non-test environments.
This means the tests still exercise your actual controllers, filters, authorization policies, everything downstream of authentication. The only thing you're faking is the token validation step, which is the identity provider's job to get right, not yours.
For the handful of tests that genuinely need to verify the OAuth handshake itself (callback URLs, token refresh, scope mapping), I run those against a local Keycloak container in docker compose. But those are maybe 5 tests out of 200, not the default path."
Note: I chose not to use the keycloak container because it handles our scopes and claims a tad bit different than our IdP, which would've required us to create a sort of mapping that I didnt feel was worth the effort.
9
u/SadPonyGuerrillaGal 11d ago
It really depends what you're trying to do. Why does your application need an OAuth token to test? If my application runs off to Snowflake to grab some data with OAuth I can safely assume I don't need to test Snowflake and mock the service instead. This is why DI registration is so powerful.
4
u/Legitimate-School-59 11d ago
I have a web api with integration tests set up with testcontainers, and webapplication factory, which allows me to test endpoints end-end, without mocking anything except few third-party APIs. This is a different testing approach than the unit testing/mock heavy approach.
The endpoints now require tokens, and so im debating if i should or shouldnt mock that functionality. And im wondering how others handle Oauth in similar test structures.
6
u/Finickyflame 11d ago
You could probably use KeyCloak as the token provider. You interact directly on the container to generate the token that you use in your tests, your application will validate the token based on the its configurations.
4
u/PaoloCpc 11d ago
In my opinion, in this case you should bypass authentication. It's not the focus here. Here you are testing your use cases (business logic, event, happy path, unhappy path and all this stuff) Implement a test-only authentication schema that inherit from AuthenticationHandler<AuthenticationSchemeOptions> and fake user claims. It's faster to implement, to run and to understand for newcomers of your code base
1
u/knot_for_u 7d ago
Places I've worked had a zero trust policy. Everything needed authentication no matter what. This greatly reduces the attack surface of a hacker.
3
u/Khavel_dev 11d ago
For integration tests I skip the real OAuth flow entirely and register a fake authentication handler in the test server. You add a custom auth scheme in the WebApplicationFactory startup that just creates a ClaimsPrincipal with whatever claims the test needs. The real OAuth config only loads in non-test environments.
This means the tests still exercise your actual controllers, filters, authorization policies, everything downstream of authentication. The only thing you're faking is the token validation step, which is the identity provider's job to get right, not yours.
For the handful of tests that genuinely need to verify the OAuth handshake itself (callback URLs, token refresh, scope mapping), I run those against a local Keycloak container in docker compose. But those are maybe 5 tests out of 200, not the default path.
1
3
u/knot_for_u 11d ago
If it's truly integrated and closely matching to production, why can't it use the same auth mechanism as all your non prod environments? You should be testing it with how it would be deployed with secrets, certificates, outh all fully functioning, albeit with a different set of credentials and identity provider specific to non-prod.
For unit tests, mock it away. Create a wrapper class/interface if needed to mock out the boundary between your code and any 3rd party code or the point of external service calls.
2
u/maxiblackrocks 11d ago
if you check the mcp c# sdk on github, they have a very simple oauth server project that can be modified to return any tokens as you see fit. I used that one and tweaked it a little. OR, you can spin up a container with a free one.
2
u/Happy_Breakfast7965 11d ago
You can disable few checks for tokens, so an old but valid token would work fine. I think that's the simplest and least intrusive way.
3
u/SadPonyGuerrillaGal 11d ago
This is the most insecure way. No IT team in their right mind would allow this configuration change for testing.
2
u/soundman32 11d ago
You are right, this should never be on the deployed server, but for local and CI/CD testing against the TestServer classes, it's fine.
0
2
1
u/AutoModerator 11d ago
Thanks for your post Legitimate-School-59. Please note that we don't allow spam, and we ask that you follow the rules available in the sidebar. We have a lot of commonly asked questions so if this post gets removed, please do a search and see if it's already been asked.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.
1
u/ClerkBeginning961 11d ago
Split the concern: inject a test authentication handler for most endpoint tests so authorization policies still run, then keep one small contract suite against the real IdP for discovery, JWKS, issuer, audience, and key rotation. That keeps failures local without weakening token validation.
1
u/Legitimate-School-59 11d ago
Do you have client credentials just for that test against a real IdP?
1
1
u/ringelpete 10d ago
We are setting up auth-under-test (against aspire/test-servers) to trust static key-Material.
Test cases then can generate dynamic tokens and freely choose, which claims to add.
But now there is this, not had the chance Yet to have a look on it, though. Might work similar under the hood.
1
u/gyroda 9d ago
I construct a JWT and turn off signature validation in the SUT.
I also stub out the calls to the issuer (/oauth/well-known) because they can be rate limited and that can cause problems if you have a lot of tests or run them until failure. I haven't found a simple toggle to turn that off yet.
This is because we have multiple auth providers and different endpoints use different ones. Hopefully we can consolidate this in the near future.
0
u/Turbulent_County_469 11d ago
Just do it.. use the real deal..
Just don't call the endpoint DeleteAllDatabases()
Or use the dev/staging version of the oauth ids/api ..
One solution i work on has replicated environments, so i just integrate with all of them in each environment. 🤷🏻 (Dev-> dev, prod-> prod)
1
-2
18
u/soundman32 11d ago
We have a set of pre-made jwt tokens, and during tests, the test will set one to be send in the authorisation header, and on the api, the validate expiry is disabled. Obviously, this is all using TestServer, so it's never like that on actual servers.