feat(auth): add TokenFetcher interface and token abstraction - #1141
Closed
TerryHowe wants to merge 2 commits into
Closed
feat(auth): add TokenFetcher interface and token abstraction#1141TerryHowe wants to merge 2 commits into
TerryHowe wants to merge 2 commits into
Conversation
Introduce TokenFetcher interface with Distribution, OAuth2, and Composite implementations extracted from the auth client monolith. Adds: - token.go: TokenFetcher interface, TokenParams, and concrete implementations - token_test.go: full coverage for all TokenFetcher implementations - client.go: TokenFetcher field, ForceBasicAuth field, SetLegacyMode(), replace exported ForceAttemptOAuth2 with unexported legacyMode - client_test.go, scope_test.go, example_test.go: update for API changes Depends on: internal/authtype (already merged) Signed-off-by: Terry Howe <terrylhowe@gmail.com>
TerryHowe
requested review from
Wwwsylvia,
sabre1041 and
shizhMSFT
as code owners
April 7, 2026 11:43
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1141 +/- ##
==========================================
+ Coverage 83.05% 83.20% +0.14%
==========================================
Files 81 82 +1
Lines 5684 5793 +109
==========================================
+ Hits 4721 4820 +99
- Misses 595 600 +5
- Partials 368 373 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Member
Author
|
Splitting this PR into three smaller, individually reviewable PRs as discussed:
Closing this PR in favor of the split. Please review the new PRs in that order — #1180 first since #1181 depends on it. |
TerryHowe
added a commit
to TerryHowe/oras-go
that referenced
this pull request
Jun 22, 2026
Add a ForceBasicAuth bool field to auth.Client. When true, a Bearer challenge from the registry is rewritten to a Basic challenge before credential handling. This is useful for registries that advertise Bearer auth but also accept HTTP Basic for the same credential pair. Implementation is a three-line scheme rewrite in Client.Do(), applied right after parseChallenge() and before the scheme switch, so the rest of the basic-auth path runs unchanged. The override bypasses bearer flow entirely, so it does not interact with the token-fetching logic. Refs oras-project#1141 (split: PR C of A/B/C). Independent of PRs A and B. Signed-off-by: Terry Howe <terrylhowe@gmail.com>
TerryHowe
added a commit
to TerryHowe/oras-go
that referenced
this pull request
Jun 22, 2026
…acyMode
Replace the exported ForceAttemptOAuth2 bool field on auth.Client with an
unexported legacyMode field plus a public SetLegacyMode(bool) setter,
and flip the default behavior:
Before: distribution-spec token endpoint was the default for
username+password; callers opted into OAuth2 with
ForceAttemptOAuth2 = true.
After: OAuth2 password grant is the default for username+password;
callers opt into the legacy distribution-spec path with
client.SetLegacyMode(true).
BREAKING CHANGE: callers that previously relied on the implicit
distribution-spec default (i.e. did not set ForceAttemptOAuth2 and
authenticate via username+password) must now call SetLegacyMode(true) to
preserve the old behavior. Callers that explicitly set
ForceAttemptOAuth2 = true should drop that line (OAuth2 is the new
default). The selection logic itself is unchanged.
Tests are updated accordingly: distribution-spec tests now call
SetLegacyMode(true); OAuth2-forcing tests drop the field. Adds
TestClient_SetLegacyMode for the new setter.
Refs oras-project#1141 (split: PR A of A/B/C).
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
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
TokenFetcherinterface withDistribution,OAuth2, andCompositeimplementations extracted from the auth client monolithForceAttemptOAuth2field with unexportedlegacyMode+ publicSetLegacyMode()setter for cleaner APIForceBasicAuthfield to force HTTP Basic auth regardless of registry-advertised schemeTokenFetcherfor advanced bearer token scenariosDetails
The auth client previously had all token-fetching logic inlined. This PR extracts it into a
TokenFetcherinterface, making it composable and testable independently:TokenFetcher— interface withFetchToken(ctx, TokenParams, Credential) (string, error)DistributionTokenFetcher— fetches tokens via the distribution spec (basic auth to token endpoint)OAuth2TokenFetcher— fetches tokens via OAuth2 password/refresh grantCompositeTokenFetcher— selects between the above based on credential typeThe
Clientstruct gains aTokenFetcherfield; if set, it is used instead of the built-in logic. ThelegacyModefield (replacingForceAttemptOAuth2) preserves backward-compatible behavior for registries that don't support OAuth2.Depends on
internal/authtype— already merged (feat: add internal authtype package #1134)Test plan
token.gofully covered bytoken_test.goclient_test.goupdated forSetLegacyMode()/ForceBasicAuthAPIgo test ./registry/remote/auth/...🤖 Generated with Claude Code