Skip to content

Commit

Permalink
Ignore http credentials with empty usernames
Browse files Browse the repository at this point in the history
  • Loading branch information
abn committed Nov 17, 2024
1 parent 2d3871d commit 640ca13
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 18 deletions.
11 changes: 11 additions & 0 deletions docs/repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,17 @@ You can prevent this by adding double dashes to prevent any following argument f
poetry config -- http-basic.pypi myUsername -myPasswordStartingWithDash
```

{{% note %}}
In some cases like that of [Gemfury](https://gemfury.com/help/errors/repo-url-password/) repositories, it might be
required to set an empty password. This is supported by Poetry.

```bash
poetry config http-basic.foo <TOKEN> ""
```

**Note:** Usernames cannot be empty. Attempting to use an empty username can result in an unpredictable failure.
{{% /note %}}

## Certificates

### Custom certificate authority and mutual TLS authentication
Expand Down
17 changes: 4 additions & 13 deletions src/poetry/utils/password_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,23 +196,14 @@ def get_http_auth(self, repo_name: str) -> dict[str, str | None] | None:
username = self._config.get(f"http-basic.{repo_name}.username")
password = self._config.get(f"http-basic.{repo_name}.password")

# we only return None if both values are None or ""
# password can be None at this stage with the username ""
if (username is password is None) or (username == password == ""):
if not username:
return None

if not password:
if self.use_keyring:
password = self.keyring.get_password(repo_name, username)
elif not username:
# at this tage if username is "" or None, auth is invalid
return None

if not username and not password:
return None
if not password and self.use_keyring:
password = self.keyring.get_password(repo_name, username)

return {
"username": username or "",
"username": username,
"password": password or "",
}

Expand Down
5 changes: 2 additions & 3 deletions tests/utils/test_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def test_authenticator_uses_empty_strings_as_default_password(
assert request.headers["Authorization"] == f"Basic {basic_auth}"


def test_authenticator_uses_empty_strings_as_default_username(
def test_authenticator_ignores_empty_strings_as_default_username(
config: Config,
mock_remote: None,
repo: dict[str, dict[str, str]],
Expand All @@ -170,8 +170,7 @@ def test_authenticator_uses_empty_strings_as_default_username(
authenticator.request("get", "https://foo.bar/files/foo-0.1.0.tar.gz")

request = http.last_request()
basic_auth = base64.b64encode(b":bar").decode()
assert request.headers["Authorization"] == f"Basic {basic_auth}"
assert request.headers["Authorization"] is None


def test_authenticator_falls_back_to_keyring_url(
Expand Down
4 changes: 2 additions & 2 deletions tests/utils/test_password_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def test_set_http_password(
("username", "password", "is_valid"),
[
("bar", "baz", True),
("", "baz", True),
("", "baz", False),
("bar", "", True),
("", "", False),
],
Expand Down Expand Up @@ -134,7 +134,7 @@ def test_set_http_password_with_unavailable_backend(
("username", "password", "is_valid"),
[
("bar", "baz", True),
("", "baz", True),
("", "baz", False),
("bar", "", True),
("", "", False),
],
Expand Down

0 comments on commit 640ca13

Please sign in to comment.