-
Notifications
You must be signed in to change notification settings - Fork 232
Additional OAuth2 Authentication for Hosted Repositories #2588
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
Conversation
update with latest changes
Sorry for the late reply, I'm just catching after vacation. See discussion in: If you are willing to work on working on this, I'm happy to help designing, reviewing and landing a solution. I agree, that solving authentication for third-party pub servers is important. I know a few organizations that currently have a custom pub server and rely on network security by having the pub-server behind a VPN. But this hardly ideal. A few notes here:
I'm happy to continue the discussion here, but if you're interesting in working on the approach outlined in #1381 please leave a comment at the end of the thread, and file a WIP PR as soon as you're getting started :) |
Sure. I am happy to help. I started with these changes as I needed Oauth2 for my firm's requirement. I would like to keep Oauth and extend it to tokens. Tokens and other information could then be stored in secrets.json as you recommended. However, I didn't understand the one with login and logout. My understanding was that we would require to log in only if we are publishing or getting anything for a repo that requires authentication. Also, I would like some version of this in production sooner so that I can use it for my firm. We also need to consider how to sign in in CI/CD environments, silently without needing a sign in the authorization. I am happy to continue working on this. Can I convert this PR into WIP PR? |
I thinking was that using tokens would solve this problem.
Really, you would like to be using oauth2.. Hmm.. |
My team is using GCP. I am hosting our pub server as a service on Cloud run. So I use the oauth2 to make sure a developer in my team who has been given access to our GCP resources is permitted to publish and get packages. This way I figured that I would just reuse what gcloud SDK would have a developer do otherwise. Maybe this is not the right approach. |
hmm, I have considered letting 3rd party pub servers use oauth2, well, openid-connect (OIDC) really.. I'm no OIDC expert, but I suspect that something like OIDC Discovery could be used to find issuer and OIDC metadata.
I'm not entirely sure if the above is how OIDC discovery is intended to be used. The "Resource" ("Entity that is the target of a request in WebFinger.") is a bit weird and seems unnecessary to me. But I suppose maybe the spec assumes that users could be on different servers. In any case, this seems VERY complicated. If someone wants to investigate these specs and figure out the right way to do this I'm very interested. But even with all that, this wouldn't work Google OIDC, because while Google does serve the OIDC configuration metadata, Google still requires your app to be registered, and Google requires there to be a secret token (for the oauth2/oidc flow). Otherwise, the idea that a pub server would simply point to a server that has a Disclaimer: I did not read the OIDC specs in detail, the above might be total nonsense.
I'm not sure what this means. Can you elaborate? Maybe we could tweak the flow a bit... Imagine a name: mypkg
version: 1.0.0
# this is the key that makes it publish to a third-party pub server
publish_to: https://mypubserver.com
dependencies:
retry: ^3.0.0 # get package retry from pub.dev
mypkg_helper: # Package from my own pubserver
version: ^1.0.0
hosted:
name: mypkg_helper
server: https://mypubserver.com (this actually works today, it's just the authentication that isn't working right). Now, imagine I do: (A) (B) Prompt for secret
(C) Login before publishing
(D) Publish with
In this case the idea is that That would allow arbitrarily complex authentication schemes for the paranoid people :D I personally think that (A), (B) and (C) will cover most common use-cases, and are rather easy to understand and use for the end-users. I'm less sure about (D), I suppose there are many different ways (D) could be configured too. An environment variable is just one way that could be used to inject an authentication provider.
This is part of the reason I figured that simple static tokens would be preferable for 3rd party pub servers.
Your understanding is correct. We would only login when a repo requires authentication, and ideally we would detected this by trying and receiving a 401 response with However, once logged in, the And with secrets stored in the PUB_CACHE, it might be nice with a I could also imagine a These are more nice to have features that makes the authentication stuff feel more complete. You can also imagine that |
Hmm, thinking more about this maybe (D) is way too complicated and unnecessary at this time. (B, example 2) Prompt for secret
Notice that, that:
But by allowing the server to inject a short custom message through the The only downside, is that the user will have to copy the token from the browser window to the terminal. This could be automated by letting the Having to copy a token from the browser window to a terminal prompt isn't pretty, but it works, and it's easy to understand. |
sorry, the latest comment got lost in my mails. Sure, I will look into B) this weekend. How do the contributions work usually ? should I just keep pushing proposed changes and you would review it? |
We can do that... Are we in agreement that we should just stick to (A) and (B), maybe (C), but not (D) or anything complicated with oauth2? If so I think it would be a great idea to start writing up a PR. Please file WIP PR, as you're making progress, and feel free to ping me with any questions. Ideally we want to do some reviews along the way. I honestly have no idea how complicated this will turn out to be. |
I really think we need to start with a simple token/secret at first for both get and publish. This token needs to be taken into the api as a header value. The hosted server should pick it up there to continue. https://docs.microsoft.com/en-us/nuget/consume-packages/consuming-packages-authenticated-feeds Important thereby that this just works in ci environments. It is just a file that is placed in the same location as pubspec so it can be under source control. |
Yes, (A) and (B).
I think the pub client should manage storage of secrets, and prompt for them when they are necessary.
I agree, working under CI is important. But storing credentials under version control sounds very wrong to me. For CI, maybe we can solve it, by allowing injection of secrets through environment variables or global config files. Maybe we should start with (A) and (B), move on to (C) and eventually extend (B) to also automatically detect the need for secrets when running |
I think it's a good idea in the future. Prompting will be complicated, because it would depend on the auth mechanism used. With oAuth it is clear, but other mechanisms are not that simple. Basic Authentication, Api Key authentication, Token authentication, etc. How would you prompt? By asking in clear text the values? (see note hereunder).
Exactly. As with Nuget, you can choose to store your credentials via clear text (not preferred) and by environment variables. So think we should define a json structure that can be used both global and local (in the repository) based upon the url of the package server. Is there a way here on the repo to start working on the specs first? Should we create an issue for this, or something else? |
Filing an issue is fine. A PR with a markdown file in
How is oAuth clear? will the user have to supply the oauth2 OIDC configuration for the server? Are do we automatically detect this? I might be missing some obvious solution here. (The oauth2 token used to authenticate against
I imagine that the simplest option is to ask users to just enter a I agree these solution is a bit naive, but it's simple. The only other elegant auth-flow I can think of is generating a random Then the client could authenticate with But I think this might be a bit too complicated, and I'm not 100% sure about the security of such a scheme. |
I will contact you through email as I already did an implementation and would like to discuss. |
I did the necessary changes on this PR #2654 |
Closing in favor of #3007 |
Business Case
As developers develop more packages in
dart
andFlutter
, they might want to keep some of the packages as private for IP purposes. Hence the pub should be able to fetch both from the public 'pub.dartlang.org' as well as any hosted server that is secured by Oauth2 (so that only their engineers canget
orpublish
the packages). I believe this ability is also important to foster open source projects as it provides companies with more flexibility to invest indart
and 'Flutter`.Proposal
Add additional Authentication configurations for hosted urls.
<HOSTURLNAME>_config.json
with parametersidentifier
(pub client's OAuth2 identifier),secret
(pub client's OAuth2 secret), authorization and token endpoints, scopes,useIdToken
(to decide whether to send id token or access token to send inAuthorization
header), and a URL to redirect once the authorization is successful. This is exactly same as how it is handled for 'pub.dartlang.org'.Changes
access token
oridentity token
inAuthorization
header.lish.dart' - to pass the hosted URL from the
serveroption to
hosted.dartand
oauth2.dart.`Help Required
I really believe in the value this would provide to the community. I have tested scenarios manually. However, I am unable to run the
dart
test as it says some required files are missing.I also have issues with versions. It always gets the latest version and not the one in
pubspec
.So if all looks good and these changes are acceptable, can you please help me set up the testing correctly and also suggest any new test cases, and also how do I contribute to the documentation of these changes? I am expecting these changes to flow to Flutter SDK so that I can use them with Flutter. Please let me know if there are any queries.