Skip to content
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

Support for Service Accounts? #17

Open
embario opened this issue Dec 19, 2015 · 8 comments
Open

Support for Service Accounts? #17

embario opened this issue Dec 19, 2015 · 8 comments

Comments

@embario
Copy link

embario commented Dec 19, 2015

I am trying to use this gem to authenticate my web application with the contacts API to create new contacts for a specific user. My assumption is that the underlying google account user who enables the contacts API on the console.developers.google.com portal can create service accounts that access its contact data. If this assumption is right, then using this gem should allow me to use application default credentials https://developers.google.com/identity/protocols/application-default-credentials to fetch that data using a service account instead of a Client-Server authentication workflow, which it seems that this gem primarily supports.

Any ideas on how I can use this gem to perform a server-to-server authentication workflow using application default credentials instead of a client-server one? Thanks in advance!

@draffensperger
Copy link
Contributor

You do need the user to initially authenticate with your application and if you use the appropriate parameters, you can have Google send your server a "refresh token" (see https://developers.google.com/identity/protocols/OAuth2 for the details). Then you use that refresh token on the server side later on to perform actions on behalf of the user like creating new contacts, etc.

The current version of this google_contacts_api gem doesn't support the creating of contacts yet. I have a fork of it that does, see https://github.com/CruGlobal/google_contacts_api . My plan is to get the code there cleaned up and merged into the main gem code, but it's a slow process as I get to it over time.

@embario
Copy link
Author

embario commented Dec 19, 2015

Right, but how can I initially authenticate with a user and then continuously perform API calls on behalf of that user without needing its interaction over and over again? My example is to create a website that manages my google contacts. Website visitors can put in their email address, and then the backend authenticates with the contacts API to create new contacts. In this case, I don't want to authenticate website visitors but rather authenticate my own account initially and then hang on to the token essentially forever to perform API calls. Is this possible?

@draffensperger
Copy link
Contributor

So you need to get the user's permissions initially to manage their contacts (that's the initial one-time OAuth2 process), and then if you requested a refresh token from Google, you can use the refresh token to keep getting new access tokens without any additional interaction on the user's behalf. So basically with that refresh token you can keep doing things with the user's Google contacts without further interaction from them.

Here's an example of how to use a refresh token to get an access token: https://github.com/draffensperger/miletracker/blob/ac056825cdd6693a1414dfdc4ce2dc31d3c8bfb2/app/models/google_api.rb#L67

You can't get around the initial part of asking for the user's permission to manage their Google contacts when they sign in with Google, and even the refresh token may eventually expire or get revoked by the user from the Google account security page (in another app I work on we just email users if/when that happens but I think it happens rarely). But with the refresh token you can essentially do what you want of interacting from the backend server side on the user's behalf long after they first authorized your app to manage their contacts.

@embario
Copy link
Author

embario commented Dec 21, 2015

Great, this helps out a lot. Thanks for your help!

@aliang
Copy link
Owner

aliang commented Dec 22, 2015

You really just need to pass in a client that conforms to the OAuth2 service token's API. I'm not sure if any currently maintained two-legged OAuth clients (for the service account) conform to that interface.

I should really refactor the current Api class in the gem into a more general adapter class, since the OAuth2 gem doesn't support two-legged authentication as far as I know.

@embario
Copy link
Author

embario commented Dec 22, 2015

Yeah, I'm currently abandoning the service account approach to this and just authenticating the google account for which I'm exposing functionality to see calendars and create contacts on a website.

I kinda wish that Google would better support their auth gem to handle all of these APIs in one place, rather than have them fragmented like this. Not to say that your work isn't good (it's great, thanks), but it's just a pain having to conform to different interfaces for different APIs.

@efrapp
Copy link

efrapp commented Mar 16, 2017

Hi @aliang and @draffensperger.
I want to thank you for the gem and ask you if the gem is currently supporting the creation of contacts?

Thanks for your answer.

@draffensperger
Copy link
Contributor

I forked the gem and added support for creation of contacts here: https://github.com/CruGlobal/google_contacts_api

However, I haven't gotten to cleaning that up and merging in those changes. At this point, I'm not actively developing using the gem.

Feel free to use the fork if it's helpful and even submit some of the functionality back to the main gem here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants