Skip to content

Make 401 challenge handling pluggable (IAuthChallengeHandler) #405

Description

@akashsinghal

Problem

Some registries mishandle a stale/expired cached bearer token so the client cannot recover:

  • One returns 401 with no WWW-Authenticate challenge when a stale token is presented. A cold, credential-free request to the same URL does return a usable challenge.
  • Another returns a 401 whose challenge realm points at a different host, which IRealmValidator (correctly) rejects. A cold request returns a same-host realm.

Today Client.SendCoreAsync hard-codes the challenge to token flow: an unknown/absent challenge falls through to return response1, and a disallowed/missing realm throws — neither is recoverable by a consumer, because both happen before any token-acquisition hook runs.

Proposal

Introduce IAuthChallengeHandler, letting the caller own the "401 → authorization" decision, with a default (DefaultAuthChallengeHandler) that preserves today's behavior exactly. The client keeps only the HTTP mechanics (cached-token attach, retry send, caching). Recovery for non-conformant registries lives in a consumer-supplied handler plus a shipped example — the core stays free of upstream-specific logic (unlike the previously-closed #400, which baked cold-retry into the core loop).

Contracts:

  • AuthChallengeContext — the failed exchange (original request, 401 response, parsed scheme/parameters, host, scopes, whether a cached token was attached, whether the request is replayable) plus capabilities that delegate to the client: a credential-free probe, realm validation, scope merging, cached-token lookup, and Basic/Bearer token fetch.
  • AuthChallengeResolution — scheme + token (+ cache scope key / cache flag). null means "give up; return the 401 unchanged."

Behavior-preserving: no existing test changes.

Is this direction acceptable? Implementation is ready and I am happy to open the PR.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions