Ensure cached realm credentials are applied if no password is found for index URL (#13463)

We were not correctly falling back to cached realm credentials when an
index URL was provided with only a username. This came up in a [later
comment](https://github.com/astral-sh/uv/issues/13443#issuecomment-2881115301)
on #13443 where credentials in a pip extra index in `uv.toml` were being
ignored when the same URL (but with only a username) was used at the
command line for `--extra-index-url`. I've added a test to catch this
case.

Closes #13443
This commit is contained in:
John Mumm 2025-05-15 13:36:18 +02:00 committed by GitHub
parent 12860a9041
commit 4ea44bec0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 3 deletions

View File

@ -280,7 +280,10 @@ impl Middleware for AuthMiddleware {
.map(|credentials| credentials.to_username())
.unwrap_or(Username::none());
let credentials = if let Some(index_url) = maybe_index_url {
self.cache().get_url(index_url, &username)
self.cache().get_url(index_url, &username).or_else(|| {
self.cache()
.get_realm(Realm::from(retry_request.url()), username)
})
} else {
// Since there is no known index for this URL, check if there are credentials in
// the realm-level cache.
@ -434,9 +437,15 @@ impl AuthMiddleware {
Some(credentials)
} else if index_url.is_some() {
// If this is a known index, we fall back to checking for the realm.
self.cache()
if let Some(credentials) = self
.cache()
.get_realm(Realm::from(request.url()), credentials.to_username())
.or(Some(credentials))
{
request = credentials.authenticate(request);
Some(credentials)
} else {
Some(credentials)
}
} else {
// If we don't find a password, we'll still attempt the request with the existing credentials
Some(credentials)

View File

@ -288,6 +288,36 @@ fn invalid_uv_toml_option_disallowed() -> Result<()> {
Ok(())
}
#[test]
fn cache_uv_toml_credentials() -> Result<()> {
let context = TestContext::new("3.12");
let uv_toml = context.temp_dir.child("uv.toml");
uv_toml.write_str(indoc! {r#"
[pip]
extra-index-url = ["https://public:heron@pypi-proxy.fly.dev/basic-auth/simple/"]
"#})?;
// Provide an extra index with the same username and URL as in `uv.toml` but
// no password.
uv_snapshot!(context.pip_install()
.arg("iniconfig")
.arg("--extra-index-url")
.arg("https://public@pypi-proxy.fly.dev/basic-auth/simple/"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
Resolved 1 package in [TIME]
Prepared 1 package in [TIME]
Installed 1 package in [TIME]
+ iniconfig==2.0.0
"
);
Ok(())
}
/// For indirect, non-user controlled pyproject.toml, we don't enforce correctness.
///
/// If we fail to extract the PEP 621 metadata, we fall back to treating it as a source