How to add scopes to explicit HTTP requests to Google Calendar API? - python

I am try to called the Calendar REST api using python's requests library in a django web application. I have made use of django-social-auth to login the user using Google accounts.
Following the related code for requests -
def index(request):
if request.user.is_authenticated:
social = request.user.social_auth.get(provider='google-oauth2')
response = requests.get('https://www.googleapis.com/calendar/v3/users/me/calendarList',
params={'access_token': social.extra_data['access_token']})
print(response.text)
return render(request, 'main/index.html')
I am getting the following error message in the response body -
Insufficient Permission: Request had insufficient authentication scopes.
I am guess we have to add a scopes variable to the request but not quite sure how to do that.

You might want to follow the offical Python sample Python quickstart
Scopes is just an array so you should be able to add more then one. Remember though if you change the scope in your code you need to reauthencate the user before its going to pick up the change so the user has to grant consent to the new scope.
from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
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 = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('calendar', 'v3', credentials=creds)
# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
print('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now,
maxResults=10, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
print('No upcoming events found.')
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
print(start, event['summary'])
if __name__ == '__main__':
main()

Related

Gmail-API with python

i'm building python GMAIL API for checking emails for 10 email accounts
but in google documentation not very useful.
this seems only support one account
https://github.com/suleenwong/Gmail-API-Python
If we check the default sample python quickstart This sample was designed to be single user but that can be changed.
The following section creates a token.json file when the user authorizes the application. The file will contain the access token and refresh token for the user who authorized the code.
If the file does not exist then the app will prompt the user to authorize it. If it does then the app will load the credentials from that file and run the code with the authorization of that user.
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
To add more users you can simply rename that file tokenUserOne.json, tokenUserTwo.json. Then set it up so that you can supply the file name you want your script to run on. You will only need to authorize each user once. As long as you have a token.json file for each user separated, your app can then be started using which ever token file you want, to access each users data.
https://developers.google.com/gmail/api/quickstart/python -this is the proper documentation everything you need is in here
aka (you also need a client_secet.json file but you will have to get yourself for the google cloud dashbord):
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def main():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
# Call the Gmail API
service = build('gmail', 'v1', credentials=creds)
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
if not labels:
print('No labels found.')
return
print('Labels:')
for label in labels:
print(label['name'])
except HttpError as error:
# TODO(developer) - Handle errors from gmail API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()

How access a website page with Google credentials using python?

I have tried access a Google ecosystem page after get credentials. My app will manage Calendar events, using python and Google api. I've got credentials, list events, read summaries, etc. But If I try to access a web page as (with AuthorizedSession class):
https://calendar.google.com
I notice that this page asks for login/password from Google.
Maybe this task is out of the specified scope. Ideas?
Thanks in advance!
Code:
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.auth.transport.requests import AuthorizedSession
import pickle
import os.path
import requests
from pathlib import Path
SCOPES = ['https://www.googleapis.com/auth/calendar']
CREDENTIALS_FILE = 'client_secret_123456ABCDEFG.apps.googleusercontent.com.json'
def get_credentials():
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
CREDENTIALS_FILE, SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
return creds
authed_session = AuthorizedSession(get_credentials())
response = authed_session.request(
'GET', 'https://calendar.google.com/')
print(response.status_code)
....
The url calendar.google.com is not in the same scope than the API.
Here's a part of the API doc :
Here's the OAuth 2.0 scope information for the Google Calendar API:
Scope Meaning https://www.googleapis.com/auth/calendar read/write
access to Calendars https://www.googleapis.com/auth/calendar.readonly
read-only access to Calendars
https://www.googleapis.com/auth/calendar.events read/write access to
Events https://www.googleapis.com/auth/calendar.events.readonly
read-only access to Events
https://www.googleapis.com/auth/calendar.settings.readonly read-only
access to Settings
https://www.googleapis.com/auth/calendar.addons.execute run as a
Calendar add-on
Edit: All actions for the Google calendar API are available in the endpoints described in the doc

Is there a way to automate Oauth2.0 authentication for Google APIs through a headless browser?

I am accessing the Google Calendar API but my Oauth2.0 needs to be refreshed every week. After 7 days my authorization is expired and I must re-verify in a browser with my google account. Is there a way that I can autmoate this process each week?
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
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
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 = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
service = build('calendar', 'v3', credentials=creds)
# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
print('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now,
maxResults=10, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
print('No upcoming events found.')
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
print(start, event['summary'])
if __name__ == '__main__':
main()

Request had insufficient authentication scopes for classroom announcements

I am using python api for fetching announcements from classroom.
My code:
from __future__ import print_function
import pickle
import os.path
from os import getcwd
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
class ClassRoom:
# If modifying these scopes, delete the file token.pickle.
def announcements_list(self):
self.SCOPES = ['https://www.googleapis.com/auth/classroom.courses.readonly',
'https://www.googleapis.com/auth/classroom.announcements.readonly']
"""Shows basic usage of the Classroom API.
Prints the names of the first 10 courses the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', self.SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('classroom', 'v1', credentials=creds)
# Call the Classroom API
results = service.courses().list(pageSize=10).execute()
courses = results.get('courses', [])
announcements = []
for course in course:
announcements += service.courses().announcements().list(courseId=course["id"],
pageSize=1).execute().get("annoucements")
return announcements
cs = ClassRoom()
print(cs.announcements_list())
But the script is generating HttpError 403 error something like
"Request had insufficient authentication scopes.". Details: "Request had insufficient authentication scopes."
How to resolve this issue?
I had the same issue, delete token.pickle from your folder and execute again. it should work

How make an api call to google calendar in python without user input?

I'm trying to make a call to the google calendar api and retrieve events that i have planned. I followed the [quickstart]1 to make an api call to google calander, while on my windows desktop it opens a web browser and asks my logged in google account for access, on my centos server it opens some sort of flow to get user info, however the text is all in german so i don't really understand whats happening, anyway i'm trying to make the api call to the google calendar without user input, i have acces to their client id and client secrets, is there any example or good guide that explains me how to do this? i have seen and understands how the oath 2,0 of google works but i just fail to see how i should put this in code. The example code is below.
from __future__ import print_function import datetime import pickle import os.path from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle. SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
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 = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('calendar', 'v3', credentials=creds)
# Call the Calendar API
now = datetime.datetime.utcnow().isoformat() + 'Z' # 'Z' indicates UTC time
print('Getting the upcoming 10 events')
events_result = service.events().list(calendarId='primary', timeMin=now,
maxResults=10, singleEvents=True,
orderBy='startTime').execute()
events = events_result.get('items', [])
if not events:
print('No upcoming events found.')
for event in events:
start = event['start'].get('dateTime', event['start'].get('date'))
end = event['end'].get('dateTime', event['end'].get('date'))
print(start, event['summary'], end)
if __name__ == '__main__':
main()

Categories