Enrich Identity with upstream tokens and simplify upstreamswap#4355
Open
Enrich Identity with upstream tokens and simplify upstreamswap#4355
Conversation
Contributor
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
The auth middleware will populate upstream provider access tokens on the Identity struct, allowing downstream middleware (upstreamswap) to read tokens without coupling to the storage layer. MarshalJSON redacts token values while preserving provider keys, and both nil and empty maps are omitted via omitempty. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce a narrow UpstreamTokenReader interface that decouples the auth middleware from storage internals. InProcessService.GetAllValidTokens performs a bulk read of all upstream providers for a session, refreshing expired tokens transparently and falling back to expired tokens when refresh fails. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add GetUpstreamTokenReader to MiddlewareRunner so the auth middleware can access the bulk token reader for identity enrichment. The runner stores the reader as a separate field (set alongside the token service) avoiding type assertions. GetAuthenticationMiddleware now accepts variadic TokenValidatorOption for forward-compatible option passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add WithUpstreamTokenReader option to TokenValidator that loads all upstream provider tokens from storage when a tsid claim is present in the JWT. The enrichment happens between claimsToIdentity and context injection, populating Identity.UpstreamTokens for downstream middleware consumption. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the ServiceGetter/GetValidTokens pattern with a direct read from the pre-enriched Identity.UpstreamTokens map. The auth middleware now handles storage reads and token refresh, so upstreamswap becomes a pure reader that looks up the provider token and injects it into the request header. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The upstreamswap middleware no longer calls the token service directly, so GetUpstreamTokenService is dead code. Remove the interface method, its Runner implementation, the mock, tests, and docs reference. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c54cd11 to
0b369e5
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #4355 +/- ##
==========================================
- Coverage 68.45% 68.04% -0.42%
==========================================
Files 479 479
Lines 48642 48737 +95
==========================================
- Hits 33300 33165 -135
- Misses 12373 12483 +110
- Partials 2969 3089 +120 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
upstreamswapmiddleware was coupled to the token storage layer via aServiceGetterpattern, making it responsible for session lookup, token refresh, and error classification on every request. This moves all that complexity into the auth middleware where it belongs.tsidclaim is present, the auth middleware now bulk-loads all upstream provider tokens viaGetAllValidTokensand attaches them toIdentity.UpstreamTokens. Theupstreamswapmiddleware becomes a trivial map reader:identity.UpstreamTokens[cfg.ProviderName].main.tsidsession identifier is filtered fromPrincipalInfo.Claimsso it does not leak into webhook payloads or audit logs.GetUpstreamTokenServiceis removed from theMiddlewareRunnerinterface (no remaining callers).Closes #4139
Type of change
Test plan
task test)task lint-fix)Changes
pkg/auth/identity.goUpstreamTokensfield with redactedMarshalJSONpkg/auth/identity_test.gopkg/auth/upstreamtoken/types.goUpstreamTokenReaderinterfacepkg/auth/upstreamtoken/service.goGetAllValidTokens(bulk read with refresh)pkg/auth/upstreamtoken/service_test.gopkg/auth/token.goWithUpstreamTokenReaderoption,loadUpstreamTokens, 503 on storage failurepkg/auth/token_test.goloadUpstreamTokens+ integration tests for full middleware pipelinepkg/auth/context.gotsidfrom externalized claimspkg/auth/utils.goTokenValidatorOptionpkg/auth/middleware.goUpstreamTokenReaderfrom runner into validatorpkg/auth/middleware_test.gopkg/transport/types/transport.goGetUpstreamTokenReader, removeGetUpstreamTokenServicepkg/transport/types/mocks/mock_transport.gopkg/runner/runner.goupstreamTokenReader, remove deadupstreamTokenServicefieldpkg/runner/runner_test.goGetUpstreamTokenReaderpkg/auth/upstreamswap/middleware.goIdentity.UpstreamTokenspkg/auth/upstreamswap/middleware_test.godocs/middleware.mdMiddlewareRunnerinterface blockDoes this introduce a user-facing change?
No. Non-AS deployments are completely unaffected (the enrichment guard is
nil-checked). AS deployments get the same token injection behavior through a different internal path.Special notes for reviewers
GetAuthenticationMiddlewareoutside the runner path pass zero options, soupstreamTokenReaderis nil and the enrichment code is unreachable.upstreamswapdistinguished infrastructure errors (503) from client errors (401). The new architecture preserves this — the auth middleware returns 503 when storage is down, andupstreamswapreturns 401 when the provider token is missing.GetAllValidTokensomits providers whose tokens expired and could not be refreshed, matchingmain's behavior.Generated with Claude Code
Large PR Justification