Skip to content

fix: Extract redirect-URL credentials on 401 even with --no-input#14182

Open
noklam wants to merge 2 commits into
pypa:mainfrom
noklam:fix/no-input-redirect-credentials
Open

fix: Extract redirect-URL credentials on 401 even with --no-input#14182
noklam wants to merge 2 commits into
pypa:mainfrom
noklam:fix/no-input-redirect-credentials

Conversation

@noklam

@noklam noklam commented Jul 16, 2026

Copy link
Copy Markdown

See issue: #14181

When an index issues a cross-origin 302 whose Location carries embedded Basic-auth credentials, the vendored requests session strips the Authorization header, so the upstream host returns 401. handle_401 is meant to recover by reading the credentials still present in resp.url and retrying, which needs no user interaction.

That recovery was gated behind use_keyring, which --no-input turns off for the default keyring provider (prompting=False). As a result --no-input silently disabled the non-interactive credential-from-URL extraction and pip returned the 401 unretried.

Call _get_new_credentials() unconditionally and gate only the keyring lookup on use_keyring. The following not self.prompting guard still returns the 401 unchanged when no credentials are found without prompting.

What does this PR do?

PR Checklist:

  • I agree to follow the PSF Code of Conduct.
  • I have read and have followed the CONTRIBUTING.md file.
  • I have added a news file fragment (or this PR does not need one).
  • I have read and followed the AI_POLICY.md file, and if any AI tools were used, I have disclosed it below.

Assisted-by: Claude Code to analyse the codebase as this is my first upstream PR.

When an index issues a cross-origin 302 whose Location carries embedded
Basic-auth credentials, the vendored requests session strips the
Authorization header, so the upstream host returns 401. handle_401 is
meant to recover by reading the credentials still present in resp.url and
retrying, which needs no user interaction.

That recovery was gated behind use_keyring, which --no-input turns off for
the default keyring provider (prompting=False). As a result --no-input
silently disabled the non-interactive credential-from-URL extraction and
pip returned the 401 unretried.

Call _get_new_credentials() unconditionally and gate only the keyring
lookup on use_keyring. The following `not self.prompting` guard still
returns the 401 unchanged when no credentials are found without prompting.

@ichard26 ichard26 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for digging into this!

new_resp = auth.handle_401(resp)

assert new_resp.status_code == 200
assert "Authorization" in sent_headers

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we want to check that the passed username and password is indeed correct?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants