Skip to content

Refactor OAuth token persistence and fix Resource/Audience conflation#4447

Open
aponcedeleonch wants to merge 1 commit intomainfrom
squashed-oauth-refactor
Open

Refactor OAuth token persistence and fix Resource/Audience conflation#4447
aponcedeleonch wants to merge 1 commit intomainfrom
squashed-oauth-refactor

Conversation

@aponcedeleonch
Copy link
Copy Markdown
Member

@aponcedeleonch aponcedeleonch commented Mar 30, 2026

Summary

  • Extract TokenPersistenceManager: Three callers shared an identical pattern — nil-check a secrets provider, fetch a cached refresh token, create an oauth2.TokenSource from it. Extract this into pkg/auth/remote.TokenPersistenceManager to eliminate the duplication. FetchRefreshToken is provided separately from RestoreFromCache so callers can do the cheap secret lookup before paying the cost of OIDC network discovery.
  • Generalize RegistryOAuthConfigOAuthConfig: Rename and move to pkg/config with a new Resource field (RFC 8707) and an injectable configUpdater callback, decoupling the token-source from pkg/config internals so enterprise callers can supply their own persistence logic.
  • Fix Resource vs Audience conflation: Audience (a provider-specific authorization URL parameter, e.g. Auth0) was being passed where Resource (RFC 8707 resource indicator, sent to the token endpoint) was expected. Resource now flows to CreateOAuthConfigFromOIDC and Audience is routed into OAuthParams["audience"].

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Refactoring (no functional changes, no API changes)

Large PR Justification

Of the 990 lines changed, 813 are test code (82%) and only 177 are production code across 7 files. The production changes cannot be split because:

  • Atomic refactoring: The RegistryOAuthConfigOAuthConfig rename touches every caller site simultaneously — leaving half the callers on the old type would not compile. The new Resource field, configUpdater callback, and TokenPersistenceManager extraction are consumed by the same call chains, so they must land together.
  • Bug fix requires the refactoring: The Resource/Audience conflation fix depends on the new OAuthConfig.Resource field introduced by the rename. Shipping the fix without the generalization would require a throwaway intermediate step.
  • Test-only bulk: The 813 lines of new tests are regression guards for the bug fix and previously-untested code paths (buildOAuthFlowConfig, wrapWithPersistence, resolveClientCredentials, configUpdater callback). Stripping them into a follow-up PR would leave the bug fix unguarded during review.

Test plan

  • New unit tests added for TokenPersistenceManager.FetchRefreshToken (all paths)
  • New unit tests added for buildOAuthFlowConfig Resource-vs-Audience split — critical regression guard ensuring Audience lands in OAuthParams["audience"] and Resource does NOT appear there
  • New unit tests added for injectable configUpdater callback invocation
  • New unit tests added for handler.buildOAuthFlowConfig endpoint-override logic
  • New unit tests added for handler.wrapWithPersistence persistence callbacks
  • New unit tests added for handler.resolveClientCredentials priority logic
  • All existing tests pass: go test ./pkg/auth/remote/... ./pkg/registry/auth/... ./pkg/config/...

Does this introduce a user-facing change?

No. This is an internal refactoring and bug fix in the OAuth token persistence layer. The Resource/Audience fix corrects incorrect token requests for RFC 8707-compliant servers and Auth0-style providers, but the CLI interface and configuration schema are unchanged.

Generated with Claude Code

@github-actions github-actions bot added the size/XL Extra large PR: 1000+ lines changed label Mar 30, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

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 transformation

Alternative:

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.

@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Mar 30, 2026
@github-actions github-actions bot dismissed their stale review March 30, 2026 15:32

Large PR justification has been provided. Thank you!

@github-actions
Copy link
Copy Markdown
Contributor

✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 30, 2026

Codecov Report

❌ Patch coverage is 62.06897% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.74%. Comparing base (c63b9eb) to head (b3652de).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/registry/auth/auth.go 20.00% 8 Missing ⚠️
pkg/auth/remote/handler.go 0.00% 7 Missing ⚠️
pkg/registry/factory.go 0.00% 4 Missing ⚠️
pkg/registry/auth/oauth_token_source.go 89.47% 1 Missing and 1 partial ⚠️
pkg/registry/auth/login.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4447      +/-   ##
==========================================
+ Coverage   69.60%   69.74%   +0.14%     
==========================================
  Files         490      491       +1     
  Lines       50269    50324      +55     
==========================================
+ Hits        34988    35100     +112     
+ Misses      12595    12538      -57     
  Partials     2686     2686              

☔ View full report in Codecov by Sentry.
📢 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.

@aponcedeleonch aponcedeleonch force-pushed the squashed-oauth-refactor branch from 0dc7c05 to 8f5b6a7 Compare March 30, 2026 15:35
@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Mar 30, 2026
@aponcedeleonch aponcedeleonch force-pushed the squashed-oauth-refactor branch from 8f5b6a7 to 18e05e5 Compare March 30, 2026 15:39
@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Mar 30, 2026
Extract TokenPersistenceManager to pkg/auth/remote to eliminate the
repeated nil-check + fetch-cached-token + create-token-source pattern
shared by three callers. Generalize RegistryOAuthConfig to OAuthConfig
in pkg/config, adding a Resource field (RFC 8707) and an injectable
configUpdater callback so callers can supply their own persistence logic.

Fix a bug where Audience (provider-specific, e.g. Auth0) was passed
where Resource (RFC 8707 resource indicator) was expected: Resource now
flows to CreateOAuthConfigFromOIDC and Audience is routed into
OAuthParams["audience"] for authorization URL parameters.

Add field-level doc comments to OAuthConfig clarifying the distinction
between Audience and Resource. Fix %w error wrapping in tryRestoreFromCache
and tryRestoreFromCachedTokens. Convert configUpdaterFunc from a type alias
to a named type.

Add unit tests covering: FetchRefreshToken direct paths, the
Resource-vs-Audience split in buildOAuthFlowConfig (regression guard),
configUpdater callback invocation, endpoint-override logic,
wrapWithPersistence persistence callbacks, and resolveClientCredentials
priority logic.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@aponcedeleonch aponcedeleonch force-pushed the squashed-oauth-refactor branch from 18e05e5 to b3652de Compare March 31, 2026 13:09
@github-actions github-actions bot added size/XL Extra large PR: 1000+ lines changed and removed size/XL Extra large PR: 1000+ lines changed labels Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL Extra large PR: 1000+ lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant