I cant use OAuth2 authentication for accessing Google cloud print as I can't have a browser redirection for account selection. So I am trying out Google service account for accessing Google cloud print (suggested method for these scenarios). But under the googleapiclient.discovery , I am unable to find a key word for cloud printing. This is the code snippet which I tried.
from google.oauth2 import service_account
import requests
SCOPES = ['https://www.googleapis.com/auth/cloudprint']
SERVICE_ACCOUNT_FILE = 'secret.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
sqladmin = googleapiclient.discovery.build('sqladmin', 'v1beta3', credentials=credentials)
I am confused at 2 places in the above code snippet.
1. If the scope provided is valid
2. What is the alternative for argument sqladmin in googleapiclient.discovery.build() function for Google cloud print.
Related
I am trying to open a private google sheet using python. The end goal here is to read that private sheet data into a json object. I have made sure to create a google cloud project, enable the API's, and service account. The service account email has been shared and added as an editor. I also created OAuth keys for a desktop application. This is required since the file is private.
I know I need to somehow request a token to use for access to the sheets API, but I am at a loss for how to create a request, and utilize the client_secret file generated from OAuth keys. I figured the googleAPI would have a function where you can pass this file directly, but I am lost in documentation.
Any insight would be appreciated!
All you need to do is supply the library with the location of the clientSecret.json file you should have downloaded from Google cloud console. This method should build the service for you and you can make the requests to the api. It will handle all the authorization.
from apiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
def get_service(api_name, api_version, scopes, key_file_location):
"""Get a service that communicates to a Google API.
Args:
api_name: The name of the api to connect to.
api_version: The api version to connect to.
scopes: A list auth scopes to authorize for the application.
key_file_location: The path to a valid service account JSON key file.
Returns:
A service that is connected to the specified API.
"""
credentials = ServiceAccountCredentials.from_json_keyfile_name(
key_file_location, scopes=scopes)
# Build the service object.
service = build(api_name, api_version, credentials=credentials)
return service
The best example I know of for service account authentication with python is the Google analytics quickstart If you have any issues altering it for google sheets let me know i can try and help.
Calling it should be something like this.
def main():
# Define the auth scopes to request.
scope = 'https://www.googleapis.com/auth/spreadsheets'
key_file_location = '<REPLACE_WITH_JSON_FILE>'
# Authenticate and construct service.
service = get_service(
api_name='sheets',
api_version='v4',
scopes=[scope],
key_file_location=key_file_location)
data = your_method_to_call_sheets(service)
How to create clientSecret.json remember to enable the google sheets api under libary
I'm trying to get a simple script (python) to work against the google calendar API and don't seem to be able to get the authentication to work properly. Its for a basic raspberry pi based thing I'm trying to make at home, and I need to just grab all the events from my google calendar.
I started with the code examples on the website, but because my script is totally server side, There was no way I could get the auth challenge step to work properly (it tried with lynx, but didn't work)
I then found examples with a service account - which seemed like the right thing as it didn't need the challenge flow. Furthermore, getting the creds_with_subject, seemed like the right approach to actually get a token related to the google account that owns the calendar. I think I got it all strung together, but then I don't actually get anything listed (as a start, I was using the calendar.list() endpoint to list the calendars out). The authentication step seemed to work (no errors) - but the ensuing list was empty. I'm guessing because my service account token wasn't associated/allowed to access my google account calendar. I've enabled the calendar API in the project to which the service account belongs.
Many of the guides I found seem to mention GSuite, which its not clear if I need
So summary questions:
For this type of usage - is the service account the right approach?
If so, do I need to associate this service account with my google account (that actually owns the calendar)?
It looks like the simple API key work doesn't work any more, but thought I'd check in case there is a simpler way?
do I need GSuite?
from __future__ import print_function
import datetime
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/calendar']
def main():
"""Shows basic usage of the Google Calendar API.
Prints the start and name of the next 10 events on the user's calendar.
"""
creds = service_account.Credentials.from_service_account_file("credentials.json", scopes=SCOPES);
creds_with_subjects = creds.with_subject("<my real account>#gmail.com");
print(creds);
print(creds_with_subjects);
service = build('calendar', 'v3', credentials=creds_with_subjects)
print(creds);
print("Getting Calendar list");
page_token = None
while True:
calendar_list = service.calendarList().list(pageToken=page_token).execute()
print(calendar_list);
page_token = calendar_list.get('nextPageToken')
if not page_token:
break
if __name__ == '__main__':
main()
Creating a service account is not enough. You also have to perform domain wide delegation and impersonate your user.
The main purpose of granting domain-wide authority to a service account is for these accounts to be able to access data on behalf of a user in your domain as otherwise the service account acts like just another account and it is trying to access its own data from Calendar, hence the empty response you are receiving.
To impersonate your user, you will have to follow the steps below:
Create a Credentials object from the service account's credentials and the scopes your application needs access to:
from google.oauth2 import service_account
SCOPES = ['SCOPE1', 'SCOPE2', ...]
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
Delegate domain-wide authority:
delegated_credentials = credentials.with_subject('YOURADDRESS#DOMAIN.COM')
However, in order to do this, you need to have a Google Workspace domain.
Reference
Using OAuth 2.0 for Server to Server Applications;
Authorizing Requests to the Google Calendar API.
I want to write a file in a Team Drive from a GAE (standard) in Python 37. I added its service account to my Team Drive members. But I cannot use the default App Engine Credentials to write.
I cannot use App Engine APIs because they are not available in GAE Standard for Python 37.
from google.auth import default
from googleapiclient import discovery
from googleapiclient.http import MediaIoBaseUpload
def upload_file_to_teamdrive(fd, file_name, team_drive_id, mime_type='application/text'):
scopes = ['https://www.googleapis.com/auth/cloud-platform', 'https://www.googleapis.com/auth/drive']
# How to get GAE Credentials ?
credentials, project = default(scopes=scopes)
drive = discovery.build('drive', 'v3', credentials=credentials)
media = MediaIoBaseUpload(fd, mimetype=mime_type)
drive.files().create(
supportsTeamDrives=True,
media_body=media,
body={
'parents': [team_drive_id], # ID of the Team Drive,
'name': file_name
},
fields='id'
).execute()
This code throw a 403 response:
googleapiclient.errors.HttpError: https://www.googleapis.com/upload/drive/v3/files?supportsTeamDrives=true&fields=id&alt=json&uploadType=multipart returned "Insufficient Permission: Request had insufficient authentication scopes."
What is the best way to write from GAE to Drive ? How my GAE could be authenticated with its service account ?
Thanks for your help.
The credentials exposed by the App Engine Environment can only authorize Google Cloud scopes, not any other Google API's scope like https://www.googleapis.com/auth/drive.
You need to use a full service account key (ideally with KMS for security) to access those APIs.
You can have a look at the library I created and always use to connect to Google APIs easygoogle
I only know how to do it with the current supported libraries - but now I need to do some work with google cloud Filestore and there is no library for it yet.
Anyone can help me out how to create a session with Python using service account?
Thanks!
Since Filestore API is discovery based you can use google-api-python-client. It is listed as supported. Alternatively you can use google-auth. Here is an example to list instances:
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
scopes = ['https://www.googleapis.com/auth/cloud-platform']
credentials = service_account.Credentials.from_service_account_file(
'/path/to/your/service_account_key.json', scopes=scopes)
authed_session = AuthorizedSession(credentials)
response = authed_session.get(
'https://file.googleapis.com/v1beta1/projects/[YOUR_PROJECT]/locations/[LOCATION]/instances')
print response.json()
You are able to manage data for Cloud Filestore from the gcloud tools
You can authenticate the gcloud tool with a service account as described here
So I'm trying to create a new calendar, but i want to be able to specify what google account to create it in, assuming i have the credentials for said account, which i do. The code bellow creates it on the currently signed in user, or requires user interaction to allow access. Is there a way to specify an user and run the command on the background. I essentially just want to add a calendar to my account when the program runs, but i cant guarantee that my account will be logged in at the time.
I believe this was possible with the version 2 of the google api through ClientLogin, but i'm trying to use version 3.
import gflags
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run
FLAGS = gflags.FLAGS
FLOW = OAuth2WebServerFlow(
client_id='MY_CLIENT_KEY',
client_secret='MY_CLIENT_SECRET',
scope='https://www.googleapis.com/auth/calendar',
user_agent='MyApp/v1')
storage = Storage('calendar.dat')
credentials = storage.get()
if credentials is None or credentials.invalid == True:
credentials = run(FLOW, storage)
http = httplib2.Http()
http = credentials.authorize(http)
service = build(serviceName='calendar', version='v3', http=http)
calendar = {
'summary': 'Test3',
'timeZone': 'America/New_York'
}
created_calendar = service.calendars().insert(body=calendar).execute()
With V3, you'll need to use a Service Account in order to act as the user. The process is described in the Google Drive documentation, you just need to use Calendar API v3 scopes and references instead of Google Drive API.
Another option would be to store the OAuth2 refresh token and use it to grab valid access tokens even if the user is not logged in. See my reply to google Calendar api v3 Auth only for first time