dermesser / yup-oauth2

An oauth2 client implementation providing the Device, Installed, Service Account, and several more flows.
https://docs.rs/yup-oauth2/
Apache License 2.0
219 stars 114 forks source link

Support Application Default Credentials #110

Open mwilliammyers opened 4 years ago

mwilliammyers commented 4 years ago

I originally opened this over in google-apis-rs/generator#20, so let me know if you think this is a better fit for that project.

What do you think about supporting Application Default Credentials? To start we could just check GOOGLE_APPLICATION_CREDENTIALS.

Down the road, we could also communicate with the metadata server to automatically obtain credentials if GOOGLE_APPLICATION_CREDENTIALS wasn’t provided. This would obviously be more involved but I think reverse engineering this process from one of the official client libraries wouldn’t be too bad.

I envision adding a new top level function like: yup_oath2:: service_account_key_from_application_default_credentials, although that is rather verbose...

So the flow would be:

Try to use an explicitly provided service account. If None, check GOOGLE_APPLICATION_CREDENTIALS (Future work) If None, communicate with metadata server to use default service account If still not found, Err.

One of the things I love about GCP (as opposed to AWS etc) is their authentication mechanism. It is so seamless and uniform across all their APIs. This would be a big step towards that UX.

Once we decide on a direction, I would be happy to open a PR.

dermesser commented 4 years ago

I am quite sympathetic towards supporting them. I also have #44 lying around for some time now, which I think is related.

The flow sounds good to me, however I am tending very much towards modular and optional approaches rather than magic intransparent ones (I want to be clear so we're on the same page). So as long as the change works well with other providers too, although yes - yup-oauth2 is mostly Google focused still, and is somewhat transparent to users of the library, I would be extremely happy to take a PR from you!

Also apologies for the delay :(

mwilliammyers commented 4 years ago

Yeah #44 and #186 are both what I am proposing here. Although I was proposing doing #44 at a later stage.

I am trying to think of the best API for this because I agree I don’t like “magic” solutions, but the entire Google Application Default Credentials flow (which is pretty much what I described above but for some reason forgot to link this) is fairly automatic/magical which is kind of its strength—to make auth a lot less of a hassle in production. I am mostly interested in this as a feature parity with official Google cloud SDK libraries.

dermesser commented 4 years ago

I think magic is fine if it is well-documented. So taking the credentials from environment variables or the GCE sidecar server is fine, if we say so in the module's documentation (and explain how it works and what to do if it doesn't).

Feature parity with google cloud libraries would be awesome!

mwilliammyers commented 4 years ago

I am hoping to have time to work this soon...

It looks like we just need to:

  1. If GOOGLE_APPLICATION_CREDENTIALS is set, call yup_oauth2::read_service_account_key() and yup_oauth2::ServiceAccountAuthenticator::builder()

  2. If not, make the equivalent HTTP request (works on GCE, GKE, App Engine, Cloud Run, and possibly more?):

    curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google"

    which returns:

    { "access_token": "...", "expires_in": 2801, "token_type": "Bearer" }
  3. Else: return an Err



In the end, I am envisioning an API that looks something like (definitely need to think of a better name):

let authenticator = yup_oauth2::ApplicationDefaultCredentialsAuthenticator::new().await?;

or we could use the builder pattern to match the other flows, but there isn't really anything to configure (pretty much the point of using ADC 🙃)... Although, there might be other things to configure, like persist_tokens_to_disk etc...

dermesser commented 4 years ago

I agree with your approaches, it looks similar to what I had thought of before. If you were to send a PR, I will gladly integrate it! For me to built/test it, I'd first have to set up a proper environment on Google Cloud again.

braincow commented 3 years ago

Boosting signal on this linked issue as well:

I have created a small bare bones impl of this and would requests comments/contributions on it before creating an pull request: https://github.com/braincow/yup-oauth2/tree/gcp_instance_metadata