Skip to content

Grant CIMD clients the server's allowed audiences - #6490

Open
alex-feel wants to merge 1 commit into
stacklok:mainfrom
alex-feel:cimd-client-audience
Open

Grant CIMD clients the server's allowed audiences#6490
alex-feel wants to merge 1 commit into
stacklok:mainfrom
alex-feel:cimd-client-audience

Conversation

@alex-feel

Copy link
Copy Markdown
Contributor

Summary

CIMD-resolved clients are built with an empty Audience list, while the token handler grants the session audience from the resource parameter (or defaults it to AllowedAudiences[0]). fosite's refresh handler validates the granted audience against the client's own list (DefaultAudienceMatchingStrategy), so every refresh_token grant from a CIMD client fails with invalid_request ("Requested audience ... has not been whitelisted by the OAuth 2.0 Client"): sign-in works, refresh never does, and every CIMD client (ChatGPT connectors, Claude Code) has to re-authorize interactively once per access-token lifespan. #3796 fixed the identical failure for DCR clients by registering them with the server's AllowedAudiences; the CIMD path never received that fix.

  • CIMDDecoratorConfig gains AllowedAudiences, threaded from the server's own AllowedAudiences at the construction site in server_impl.go.
  • buildFositeClient grants that list to every resolved client instead of nil, mirroring the DCR shape from Set audience on DCR clients for refresh token support #3796.
  • Tests: the built client carries the configured audiences, an empty config preserves the prior nil behaviour, and a regression test drives the real decorator fetch() path plus fosite.DefaultAudienceMatchingStrategy exactly as the refresh handler calls it — it fails at the pre-fix behavior with fosite's verbatim production error and passes with the fix.

Fixes #6489

Type of change

  • Bug fix

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)

go test ./pkg/authserver/... (every package this change touches, including the HTTP-level integration tests) is green locally; the full task test matrix incl. -race is left to CI (cgo unavailable on the dev machine). golangci-lint run ./pkg/authserver/... reports 0 issues.

Does this introduce a user-facing change?

Yes: clients registered via Client ID Metadata Documents can now use the refresh_token grant; previously every CIMD refresh failed with invalid_request and clients had to re-authorize each access-token lifespan.

Special notes for reviewers

  • The regression test invokes fosite.DefaultAudienceMatchingStrategy directly, mirroring handler/oauth2/flow_refresh.go's call verbatim; a full HTTP-level CIMD refresh flow would need a CIMD-document test server wired into the integration harness, which felt disproportionate for a fix this size — happy to add it if you'd prefer.
  • Touches the same buildFositeClient call line as Persist resolved CIMD clients so Redis session rehydration finds them #6284, so whichever lands second takes a small mechanical rebase.

CIMD-resolved clients were built with an empty audience list, so
fosite's DefaultAudienceMatchingStrategy rejected every refresh_token
grant with "has not been whitelisted by the OAuth 2.0 Client".
The authorization_code grant was unaffected because that path never
validates audience, so the failure only surfaced on refresh, roughly
an access-token lifetime after the first sign-in.
CIMDDecoratorConfig now carries AllowedAudiences, threaded from the
server's own AllowedAudiences at construction, and buildFositeClient
grants that list to every resolved client, mirroring how DCR clients
already inherit the server's AllowedAudiences (stacklok#3796).

Fixes: stacklok#6489
@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.23%. Comparing base (ee527be) to head (8fd8a0f).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6490      +/-   ##
==========================================
+ Coverage   78.13%   78.23%   +0.10%     
==========================================
  Files         768      769       +1     
  Lines       74649    74997     +348     
==========================================
+ Hits        58324    58676     +352     
+ Misses      16320    16316       -4     
  Partials        5        5              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jhrozek jhrozek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed with security, OAuth-correctness, code-quality, and architecture passes — no blocking issues.

This correctly mirrors the DCR audience fix from #3796 for the CIMD path. Confirmed the actual audience gate is the resource-parameter validation in token.go, not client.GetAudience(), so granting the full AllowedAudiences list here doesn't widen what tokens get issued — it just unblocks fosite's refresh-grant self-check, which was the actual bug. Test coverage is solid, including a regression test that drives fosite's real DefaultAudienceMatchingStrategy.

Two minor non-blocking nits for a follow-up if you want them:

  • CIMDDecoratorConfig's doc comment says "prevents silent swaps of the two adjacent []string fields" — there are three now.
  • buildFositeClient is up to 6 params (4 []string) — might be worth a struct given the file already uses one for the same reason elsewhere, but not required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Embedded auth server: CIMD clients get no audience, so every refresh_token grant fails

2 participants