I am trying to retreive the classwork of each course from Google Classroom API.I have succeeded in getting all the courses, but I am stuck on the course work: <HttpError 403 when requesting https://classroom.googleapis.com/v1/courses/167997334462/courseWork?alt=json returned "Request had insufficient authentication scopes.">.
This is the code I am using:
from __future__ import print_function
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/classroom.coursework.students.readonly']
def main():
"""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(
r"\test\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('classroom', 'v1', credentials=creds)
# Call the Classroom API
course_work_results = service.courses().courseWork().list(courseId="167997334462").execute()
[...]
if __name__ == '__main__':
main()
I have generated the credidentials using admin account; I've also tried several different Scopes, but same error.
Could you guys please help me here?
I am using Python 3.9.
Thanks,
Alexandru
Since you are using the scope
https://www.googleapis.com/auth/classroom.coursework.students.readonly,
I assume you are a student.
Students are only allowed to access course work of the courses where they are accepted course participants.
Trying to retrieve the course work of another course will result in an 403 error.
If you are not a student, but an Admin of your Google Workspace domain, you should use a wider scope, e.g.
https://www.googleapis.com/auth/classroom.coursework.me.readonly.
Please mind that after changing the scopes in your source code you need to delete your token file to trigger new authentication flow.
Related
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()
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
I'm trying to build a simple python script to access gmail's API and organize certain email messages inmy inbox into a csv file.
I see in the below documentation that accessing the messages is done using the user's (mine in this case) email address.
messages.list
I'm running into difficulty accessing the API. I'm getting the below error:
"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."
I was hoping to build a light weight script not a web application. Does anyone know if there is a way I can authenticate my own email address in a script?
PS: I suppose I could use selenium to automatically sign in but I was wondering if there was a way to do this using gmail's API.
You need to understand that the data you are trying to access is private user data. This is data owned by a user that being you, which means your application need to be "authorized" by the user "you" to access their data.
We do this with a method called Oauth2, it will allow your application to request consent for access to read the users emails in this case.
In order to use Oauth2 you must first register your applcation on Google Developer console and set up a few things, this will identify your application to Google.
All of this is explained in the Python quick-start for gmail. Once you have that working you should be able to change the code to use message.list instead of labels.list.
from __future__ import print_function
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/gmail.readonly']
def main():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
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('gmail', 'v1', credentials=creds)
# Call the Gmail API
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
if not labels:
print('No labels found.')
else:
print('Labels:')
for label in labels:
print(label['name'])
if __name__ == '__main__':
main()
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
Is it possible to create google contacts using the google contact APIs or people APIs?
I'm having trouble creating new contacts using the google APIs.
I'm searching for days and found the following information:
1 - Looks like the people API package comes to replace google contacts API
https://gsuite-developers.googleblog.com/2017/07/google-people-api-now-supports-updates.html
2 - Many people are unable to create new contacts with python 3+ using gdata and atom packages.
3 - people API appears as recommended by Gsuite
https://support.google.com/a/answer/6103110?hl=pt-BR
I would like to know if anyone is creating new contacts using these google APIs.
Is a g suite email required?
How do I get access token?
I've done all the setup on google cloud platform (enable APIs and auth2), i have the json file, secret key and client id
edit:
I am managing to list my 50 contacts with this code, I am having to modify the blocks to create new contacts
from __future__ import print_function
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/contacts']
def main():
"""Shows basic usage of the People API.
Prints the name of the first 10 connections.
"""
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('people', 'v1', credentials=creds)
# Call the People API
print('List 50 connection names')
results = service.people().connections().list(
resourceName='people/me',
pageSize=50,
personFields='names,emailAddresses').execute()
connections = results.get('connections', [])
for person in connections:
names = person.get('names', [])
if names:
name = names[0].get('displayName')
print(name)
if __name__ == '__main__':
main()
Since you already have auth working to list contacts, you should be able to do something like this to create one:
newContact = { "names": [{ "givenName": "John", "familyName": "Doe" }] }
result = service.people().createContact(body=newContact).execute()
The full definition of what can be in the body/person is here.