I am trying to get grades from a class's assignments but if I try to call the service.courses().courseWork().list(courseId=course['id']).execute()
it gives me
Warning: Scope has changed from "https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.coursework.me.readonly https://www.googleapis.com/auth/classroom.rosters.readonly" to "https://www.googleapis.com/auth/classroom.student-submissions.me.readonly https://www.googleapis.com/auth/classroom.courses.readonly https://www.googleapis.com/auth/classroom.rosters.readonly".
and if I change the scopes to the recommended ones, I get this.
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://classroom.googleapis.com/v1/courses/[id]/courseWork?alt=json returned "The caller does not have permission". Details: "The caller does not have permission">
my code:
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
import warnings
# Set up the OAuth2 flow
flow = InstalledAppFlow.from_client_secrets_file(
'client_secret.json',
scopes=[
"https://www.googleapis.com/auth/classroom.coursework.me.readonly",
"https://www.googleapis.com/auth/classroom.rosters.readonly",
"https://www.googleapis.com/auth/classroom.courses.readonly"
])
flow.run_local_server(port=0)
# Get the OAuth2 credentials
creds = flow.credentials
# You can then use the credentials to authenticate requests to the Google API
service = build('classroom', 'v1', credentials=creds)
# Get a list of all the courses that you are a part of
courses = service.courses().list().execute()
# Loop through the courses and print the course names and IDs
for course in courses['courses']:
print(f"Course Name: {course['name']}")
print(f"Course ID: {course['id']}")
cw = service.courses().courseWork().list(courseId=course['id']).execute()
for assig in cw['courseWork']:
print(assig)
This is a known issue and I would encourage you to upvote or comment on the corresponding Google IssueTracker ticket https://issuetracker.google.com/issues/78592659.
In the OAuth protocol, servers don't need to return the exact scopes requested. This is the case here as well as in other (non-Google) APIs. The server is returning the https://www.googleapis.com/auth/classroom.student-submissions.me.readonly
scope because it is equivalent to the the client-requested https://www.googleapis.com/auth/classroom.coursework.me.readonly
scope.
However, a dependency in the Python client library (oauthlib) is treating this scope difference as an error instead of a warning.
If it's acceptable, one solution is to set the OAUTHLIB_RELAX_TOKEN_SCOPE
variable to True
in your environment to suppress the error, as described in this answer.
My guess for the reason you are getting a 403 when you change the client-requested scope is that you may not have updated the scopes in your GCP projectwhen you changed them in your code.