App Engine OAuth2.0 authorized cron job to analyze Google Sheet - python

I'm creating a Google App Engine project which is going to automatically trigger a function each 5 minutes to analyze a Google sheet.
OAuth authorization
The to-be-analyzed sheet is a G Suite sheet, public to only company members. So I need OAuth2 to authorize the access. How do I do this?
I think I need a Service Account client ID, because as this is going to run automatically in the server, there cannot be a OAuth2 flow, right? Who is going to click the buttons if the function is ran in the server?
I need some directions.
Thanks
https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Yes, it is an OAuth2 flow, but not one involving a manual user operation - the actions are performed by the servers, automatically, based on pre-configured information. From the very document you mentioned:
The Google OAuth 2.0 system supports server-to-server interactions
such as those between a web application and a Google service. For this
scenario you need a service account, which is an account that belongs
to your application instead of to an individual end user. Your
application calls Google APIs on behalf of the service account, so
users aren't directly involved. This scenario is sometimes called
"two-legged OAuth," or "2LO." (The related term "three-legged OAuth"
refers to scenarios in which your application calls Google APIs on
behalf of end users, and in which user consent is sometimes required.)
Basically you need:
on the GAE side to locate an existing (or create a new) service account for your app (in the cloud project's IAM & Admin Service Accounts page). One service account is automatically created when your app is created.
on the G Suite side to allow access by Delegating domain-wide authority to the service account:
To delegate domain-wide authority to a service account, first enable
domain-wide delegation for an existing service account in the Service
accounts page or create a new service account with domain-wide
delegation enabled.
Then, an administrator of the G Suite domain must complete the
following steps:
Go to your G Suite domain’s Admin console.
Select Security from the list of controls. If you don't see Security listed, select More controls from the gray bar at the bottom
of the page, then select Security from the list of controls. If you
can't see the controls, make sure you're signed in as an administrator
for the domain.
Select Show more and then Advanced settings from the list of options.
Select Manage API client access in the Authentication section.
In the Client Name field enter the service account's Client ID. You can find your service account's client ID in the Service accounts
page.
In the One or More API Scopes field enter the list of scopes that your application should be granted access to. For example, if your
application needs domain-wide access to the Google Drive API and the
Google Calendar API, enter: https://www.googleapis.com/auth/drive,
https://www.googleapis.com/auth/calendar.
Click Authorize.
Your application now has the authority to make API calls as users in
your domain (to "impersonate" users). When you prepare to make
authorized API calls, you specify the user to impersonate.

Finally I solved it this way:
Setup a new App Engine service account (I don't know if a "new" one was neccesary really)
Take note of that new service account email
Share the Sheet with that service account mail (I've not yet tested it without this step)
Download its service secrets as a JSON.
Use this code(inspired in (1) and (2))
class analysisHandler(Handler):
def get(self):
credentials = ServiceAccountCredentials.from_json_keyfile_name('service-secrets.json',
["https://www.googleapis.com/auth/spreadsheets"])
http = httplib2.Http()
#if credentials are still valid
if not credentials.invalid:
logging.info("Valid credentials, entering main function")
http = credentials.authorize(http)
main(http)
else:
credentials.refresh(http)
main(http)
Then in main():
sheetService = discovery.build('sheets', 'v4', http=authorized_http)
logging.info("Reading Google Sheet")
result = sheetService.spreadsheets().values().get(spreadsheetId=spreadsheet_id, range=range_name).execute(http=authorized_http)
urlfetch.set_default_fetch_deadline(45)
logging.info("Printing in Google Sheet")
sheetService.spreadsheets().values().append(spreadsheetId=spreadsheet_id, range="Log", body=body, valueInputOption="USER_ENTERED").execute(http=authorized_http)
Where the authorized_http parameter is the one built before with credentials.authorize()
I think this can be improved however.
(1) How to use "Service account" authorization (rather than user based access refresh tokens)
(2) Creating and sharing Google Sheet spreadsheets using Python

Related

How to delegate contacts in Google Admin SDK in Python

I'm trying to delegate my Google contacts (not GMail) to another account (same Workspace). People API does not have the option to delegate contacts so I tried Google Admin SDK - Contact Delegation API. However, I can't find a way to build the resource like other APIs.
How can I create the resource and then delegate my contacts? And what is the scope I need to allow for the credentials to work?
For other APIs, I use this code :
from googleapiclient.discovery import build
# Load client_config
# Define scopes to autorize like -> scopes = ['https://www.googleapis.com/auth/admin.directory.user']
# Get the credentials into the creds variable
admin_service = build('admin', 'directory_v1', credentials=creds)
# use admin_service to create/update users in the workspace
My end goal is to use a service account with delegated access to impersonnate users and automatically delegate gmail and contacts. I've been able to get the gmail delegation to work, but not the contacts delegation.
I'm fairly new with Google APIs so I may have overlooked something in the documentation.
The issue has been closed. It was not intended to have a discovery file, thus the clients cannot use it to generate the required methods. What you need to do is to make the calls to the REST API directly. Just remember to add the OAuth token on the headers.

Revoke firebase admin credentials certificate

On a server firestore admin is accessed using python:
import firebase_admin
from firebase_admin import credentials, firestore
cred = credentials.Certificate('myfile.json')
myfile.json has been added to a git repo so now I'm wondering if there is a way to revoke it and create a new one?
Following firebase tutorials it's supposed to be a service account, however there is no old service account on google cloud to revoke.
myfile.json was created months ago so there is no way to know how it was created (as when doing anything with firebase/google cloud you have to jump around to multiple guides all over the place, out of the blue knowing all kinds of things to make any progress whatsoever).
Edit:
The reason I didn't find the service account was because google cloud had selected a project that had a similar name as the firebase project.
If you look at the contents of myfile.json, notice three fields: project_id, client_email and private_key_id
These fields tell you the Project ID that the credentials created in, the name of the service account (client_email) and the Key ID.
With that information, you can go to the Google Cloud Console. Log in and select your Project (if you manage more than one Project). Go to IAM -> Service Accounts and find the service account by the client_email. Then disable or delete the service account.
There are more advanced things that you can do such as disable a key and create another one (key rotation), but since the Service Account Key JSON file has been leaked, I would delete the service account and create a new one.

Automate report generation using Python, what kind of Credentials do I need

I have an Google Analytics Account that I want to automate some custom reports from, but I have some problems understanding what kind of Credentials I need. Most of the tutorials I have seen says I need to use OAuth client ID but the google developers console site says I need a Servide Account key.
What is the difference between the two? Using another Analytics Account I tried to setup a OAuth connection, and it worked, but I now got unsure about what kind of key I should use.
What I want to do is to just have a Python script set up to run at some times, and then to get the data I want to query for. The data is just the same as the one I can get from logging into the Google Analytics UI, so there is no need for any users to consent to giving me access to any personal data or what ever else the Consent form should be used for.
Can someone explain what the difference is between the two Credentials and what one would be the correct one to use for my project?
Both Service accounts and OAuth2 are used to access private user data. Private data is data that is accessible only by logging in. My posts on Google+ are public anyone can see them. The information in my Google Analytics is private owned by me only I can see it and those I grant access to it.
With Oauth2 access is granted at run time. The first time an application is run the user will be asked if your application can access their data. If the user accepts and grants your application access you will be given a refresh token. This refresh token can be then used to get an access token which is used to access the private user data. Access tokens are only good for about an hour. After the hour is up you use the refresh token to get access again. That's why I say access is granted at runtime. You only have to ask the user for access once to get the refresh token though.
Service accounts on the other hand are pre authenticated. Service accounts are like dummy users they have their own google drive account and google calendar account. Because if this it is possible to shire data with them like you would any other user. You take the service account email address and add it as a user under the admin section of google analytics at the ACCOUNT level it must be the ACCOUNT level. Then using the service account in your code, you will be able to access the data for that Google Analytics account without requesting authentication from a user the first time.
Service accounts are most often used by developers to grant others access to the data owned by the developer. Oauth2 on the other hand would be used to access data of your customers for whos accounts you the developer does not personally have access to.
Technically speaking you can use either for your project as long as you store the refresh token you could technically use Oauth2 for your project. However I would not recommend it refresh tokens can expire under certain circumstances, which I will not go into.
I would recommend using a service account in your case it will be much easer for you to administrate as you will only need to set it up once.
My tutorials on the subject:
Google Developer console service account
Google Developer Console Oauth2 credentials

Get the service object from access token (google-api-python-client)

The documentation google + domains api to create a post using the 'service' object, obtained here by this method. But in my project to authenticate via google and other sites I use the python social auth
and after authorization I have a ready access token.
The problem lies in the fact that I need a service object to work with api, but I can not figure out how to get it already having access token. Please help me and sorry for my english.
For the domains API, you typically will implement using a service account authorization flow - which is not retrieved in the same way as a user OAuth flow. This is because service accounts can be authorized for services that users typically should not be authorized for (e.g. retrieving domain-wide lists of user names).
The service account credentials, used to authorize your application, are created using the Google Developer Console and then are downloaded as a JSON or p12 file that is used to authenticate your Python client, as shown in this example.
That said, you still can do some actions with that access token which is why the auth flow you're seeing is doing this. Service credentials are how you should be authorizing for domains-related management features which may explain the behavior you're seeing.

Google Oauth2 in App Engine: Skip Account Selection

I am working on a Google App Engine web app which exploits the Api Client Library (Python) to access drive and calendars.
When the user enters the app it is asked to log in with a Google Account. After that a second form is shown in which the Application is said to be not affiliated to Google and the user shall authorize it to access his data. In this second form the user can change the account (if it is logged with several).
This sometimes lead to inconsistencies in the app as the users.get_current_user() returns the former Account while the services accessed through the library refer to the second account.
I have been strugling on this for a long time Managing users authentication in Google App Engine
A solution would be to avoid the second account selection and forcing the user to authorize the application against the account which is currently logged.
Is there any way of doing so?
I am using the Python decorator oauth_required() and oauth_aware()

Categories

Resources