Skip to content

Auth: Make requirement to have username in repo URL optional? Or more doc examples #750

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
glin opened this issue Mar 4, 2025 · 4 comments
Labels
feature a feature request or enhancement

Comments

@glin
Copy link

glin commented Mar 4, 2025

So in the repo auth docs, the first line does say that the username is required to be in the repo URL:

To use authentication you need to include a user name in the repository URL.
https://pak.r-lib.org/dev/reference/repo-auth.html

But I had still missed this and spent some time trying to figure out why the options(repos = method wasn't working for an authenticated repo.

Other auth methods like curl with a .netrc don't require you to put the username in the repo URL, so I believe other users may hit this gotcha as well if quickly skimming through the docs.

So a few suggestions I can think of:

  1. Add an explicit example of setting the repos option to the docs. More users will be familiar with this method, and some tools like the RStudio IDE have repo settings where you just type in a repo URL.
options(repos = c(CRAN = "http://username@127.0.0.1:11235/"))
  1. Add hints to the error messaging if you omitted a username, and some netrc/keyring credentials happen to match the URL

  2. Make the username requirement optional. With curl and .netrc, usernames are optional, and curl appears to select the first .netrc entry from quick testing:

repo <- webfakes::new_app_process(pak:::auth_proxy_app(), port = 11235)
cat <<EOF > ~/.netrc
machine 127.0.0.1
login bad
password bad

machine 127.0.0.1
login username
password token
EOF
chmod 600 ~/.netrc

curl --netrc -v http://127.0.0.1:11235
# *   Trying 127.0.0.1:11235...
# * Connected to 127.0.0.1 (127.0.0.1) port 11235
# * Server auth using Basic with user 'bad'

And it finds the right entry if the username is present:

curl --netrc -v http://username@127.0.0.1:11235
# *   Trying 127.0.0.1:11235...
# * Connected to 127.0.0.1 (127.0.0.1) port 11235
# * Server auth using Basic with user 'username'

This would just be more convenient, especially since I doubt most users are going to have multiple logins configured for the same repo anyway. And also less user configuration required when converting an unauthenticated repo to authenticated.

@glin
Copy link
Author

glin commented Mar 4, 2025

I just reread #729 and realized you wrote a similar thing there too,

I would not store the username in the repo URL, or at least that should not be required. If the username is not there, then the admin can configure repo URLs for all users easier. Again, we could follow what git does here when it looks up credentials (including usernames) from the credential store.

The admin config is also a good point. It won't be a problem with PPM since we'll be using __token__ as the username for all repo URLs, but it could be a problem for other authenticated repos.

@gaborcsardi
Copy link
Member

gaborcsardi commented Mar 4, 2025

Thanks for the thorough testing!

We need a way to opt in into authenticated repos. On some platforms searching for passwords in the system keyring may require user interaction, so we can't just start looking for every configured repository. Having a username in the repo URL seems like a good way to opt in.

But you are right about the admin config. One way to work around this is to allow an empty username in the URL. E.g. https://@example.com. Then pak would 1) first try to find the credentials with the current user's username, 2) fall back to searching for credentials without a username, and 3) use the current username in the HTTP basic auth scheme. The last one is because it is unclear what should happen if the username is empty in HTTP basic auth, so it is best not to leave it empty.

Add an explicit example of setting the repos option to the docs.

Good idea.

Add hints to the error messaging if you omitted a username, and some netrc/keyring credentials happen to match the URL

We can't really do that because we can't search for credentials if there is no @ in the URL.

Make the username requirement optional.

We cannot do that, either. Well, we can make the username itself optional, but we need to require for the user to put at least a @ into the URL.

@glin
Copy link
Author

glin commented Mar 5, 2025

I see, that makes more sense now. On Linux, I think I was using the file backend so there was no login prompt. In that case.. what about making the username optional only for .netrc, but not keyring?

Or alternatively, I was just looking at pip and uv, and both do require opt-in to keyring:
https://pip.pypa.io/en/stable/topics/authentication/#keyring-support
https://docs.astral.sh/uv/configuration/authentication/#http-authentication

But it looks like they use a CLI flag, environment variable, or pip config setting instead. That could be another option besides the empty username.

If there aren't any clear options, then I think also fine to put off for an initial release. Like I mentioned earlier, we won't have this problem with PPM since the username will always be the same. And for Workbench servers, it'll probably be the admin setting a global repo URL with credentials for all users, where the user doesn't actually have to configure anything.

@gaborcsardi
Copy link
Member

On Linux, I think I was using the file backend so there was no login prompt.

Well, because you already had your credentials set up in a keyring and the keyring was not locked. Otherwise there is definitely user interaction. (pak does not work well with the file backend btw.)

what about making the username optional only for .netrc, but not keyring?

Maybe, but I'd prefer to keep this simple, at least for the default behavior. If we have default sources of credentials and optional ones, that complicates things.

But it looks like they use a CLI flag, environment variable, or pip config setting instead. That could be another option besides the empty username.

A CLI flag is not great, at least not by itself. we'd definitely need another way that you can set globally. We don't have config settings, so I guess we are left with an env var. So how about we have an env var, and if that is set that's also an opt-in to try to authenticate all repos.

In this case I am not sure what we should do if only some repos are authenticated. I don't think that there is a real chance of sending credentials to the wrong hosts, at least not in practice, so that's ok.

I think we could give warnings for failed credential lookups when the user (or admin) has globally opted into authenticated repos.

@gaborcsardi gaborcsardi added the feature a feature request or enhancement label May 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants