CI against a real IdP with zero users

The worst time to learn your token verification is wrong is when a real user hits it. The usual alternatives are all bad in their own way: mock the IdP and test your mocks, stand up a heavyweight test realm, or skip the test and trust the library. ChirpAuth ships a fourth option: mint genuine, RS256-signed ID tokens for your own app, on demand, with no user involved.

Test tokens are real tokens

One authenticated request to the control plane gets you a signed JWT for any subject you name:

curl -X POST -H "Authorization: Bearer $DEV_TOKEN" \
  -d '{"client_id":"cs_dev_7f3a09c2…","sub":"test:alice"}' \
  https://signin.chirpauth.com/control/apps/test-tokens

What comes back is not a mock. It's an RS256 signature you verify against a published JWKS, with real issuer, audience, and expiry claims — your callback and your verification code run exactly the path they'll run in production. Pipe it straight at your own endpoint:

curl -H "Authorization: Bearer <that jwt>" https://myapp.com/auth/cb

Why this can't blow up in production

A feature like this is only safe if a test token is structurally incapable of acting like a real one. Two properties enforce that:

  1. The subject is namespaced. Test subjects are test:-prefixed, a namespace real users can never occupy. Even if a test token leaked into a production database, it identifies nobody.
  2. The clients enforce the environment axis. Every ChirpAuth SDK rejects a test token under a production configuration — and rejects a production token under a test configuration. This is conformance-tested in both directions, in all four languages. The boundary isn't a convention; it's code that fails closed.

So the worst case of a mishandled test token is a rejected request, not an impersonated user.

The hermetic option

For CI that shouldn't touch the network at all, the conformance suite ships the issuer itself as a container — the real ChirpAuth handler compiled with an in-memory store and zero AWS dependencies:

docker run -d -p 8099:8099 \
  -e CHIRP_AUTH_LOCAL_ADDR=0.0.0.0:8099 \
  ghcr.io/chirpauth/test-issuer:main
curl -s http://localhost:8099/.well-known/openid-configuration

Because it's compiled from the issuer's own source, it can't drift from production behavior the way a hand-written fake does. Your integration tests get a full OIDC issuer — discovery, JWKS, token endpoint — that starts in about a second and needs no credentials.

What your CI actually checks

With real tokens available, an auth integration test stops being "does my mock return what I told it to" and becomes:

That last test is the one that catches the deployment mistake everyone makes eventually.

Auth is the code you most need tested against the real thing and are least equipped to test against the real thing. Fixing that asymmetry costs one curl.