Skip to content

Treat the service parameter as optional in Bearer auth challenges - #901

Open
Syed-Umair wants to merge 1 commit into
apple:mainfrom
Syed-Umair:optional-service-in-auth-challenge
Open

Treat the service parameter as optional in Bearer auth challenges#901
Syed-Umair wants to merge 1 commit into
apple:mainfrom
Syed-Umair:optional-service-in-auth-challenge

Conversation

@Syed-Umair

Copy link
Copy Markdown

What

createTokenRequest rejects any WWW-Authenticate: Bearer challenge that omits service, so logging in to a registry that does not send it fails with:

cannot parse service from WWW-Authenticate header

Google Artifact Registry is one such registry. Its challenge carries only a realm:

www-authenticate: Bearer realm="https://us-central1-docker.pkg.dev/v2/token"

This makes container registry login (and therefore container image push/pull) unusable against Artifact Registry.

Why this is the right fix

service is a convention of the Docker registry token spec, not a requirement of RFC 6750 §3, so a conforming registry may omit it.

parseWWWAuthenticateHeaders already models service as optional, and AuthChallengeTests has a case for a challenge without it. Only createTokenRequest treated it as mandatory, so the parser and its one caller disagreed. This change makes the caller match the parser.

realm stays mandatory — without it there is nowhere to send the token request.

Change

  • TokenRequest.service becomes String?.
  • fetchToken appends the service query item only when the challenge supplied one.
  • createTokenRequest passes the optional through instead of rejecting nil.

A challenge that does carry service produces an identical request to before, so Docker Hub and GHCR are unaffected.

Verification

Artifact Registry issues a token when service is omitted:

$ curl -G https://us-central1-docker.pkg.dev/v2/token \
    --data-urlencode 'client_id=containerization-registry-client' \
    --data-urlencode 'scope=repository:PROJECT/REPO/IMAGE:pull,push' \
    -H 'Authorization: Basic <oauth2accesstoken:...>'
HTTP 200   {"token": "...", "expires_in": ...}

With container built against this change, against a real Artifact Registry repository:

$ container registry login -u oauth2accesstoken --password-stdin us-central1-docker.pkg.dev
Login succeeded
$ container image push us-central1-docker.pkg.dev/PROJECT/REPO/IMAGE:latest
... 100% (14 blobs, 73.0 MB)

Both fail on 1.3.1 with the error above. Pushes to Docker Hub still work.

Tests/ContainerizationOCITests/TokenRequestServiceTests.swift adds coverage for the service-less challenge, the service-present case, and the still-rejected missing realm. It compiles, but I could not execute the suite locally — swift test needs Testing.framework from a full Xcode install and every test target fails to load without it, so CI results are the ones to trust here.

`createTokenRequest` rejected any `WWW-Authenticate: Bearer` challenge that
omitted `service`, so authenticating to a registry that does not send it failed
with "cannot parse service from WWW-Authenticate header". Google Artifact
Registry is one such registry: it replies with only
`Bearer realm="https://LOCATION-docker.pkg.dev/v2/token"`.

`service` is a convention of the Docker registry token spec rather than a
requirement of RFC 6750 section 3, and `parseWWWAuthenticateHeaders` already
modelled it as optional — `AuthChallengeTests` covers a challenge without it.
Only `createTokenRequest` treated it as mandatory, so the two disagreed.

Make `TokenRequest.service` optional and omit the `service` query item when the
challenge did not supply one. A challenge that does carry `service` is
unaffected, so Docker Hub and GHCR behaviour does not change. `realm` stays
mandatory, since without it there is nowhere to send the token request.
@Syed-Umair
Syed-Umair force-pushed the optional-service-in-auth-challenge branch from 2729ca0 to 4a74154 Compare September 3, 2026 10:24
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.

1 participant