3

I am trying to access course work from my Google Classroom in a Google Apps Script using the Classroom API v1. I followed the steps in the Quickstart to successfully retrieve my course list, but when I tried to access the coursework in one of my classes using the following:

var coursework = Classroom.Courses.CourseWork.list('valid courseId');

I get a 'The caller does not have permission' error. I can successfully retrieve the coursework list using the APIs Explorer, though.

From playing with the APIs Explorer, it looks like the "classroom.coursework.students.readonly" scope is needed for this command. However, that scope doesn't get added to my project when I hit the 'Allow' button in the permission dialog. Is there a way to add it to the scope list for the project? I've searched SO and have seen mention of setting scopes in other languages (python, for instance), but not in Apps Script. I've also seen mention of someone authorizing a scope manually in an Apps Script, but with no explanation on how to do that.

I've hit a wall on this, so if anyone has a suggestion, I'd really appreciate it. Thanks.

Community
  • 1
  • 1
Joel White
  • 31
  • 1
  • 4

4 Answers4

9

Originally addressed by me on this SO thread.

The appropriate Classroom API reference for this task is here.

Looks like even after enabling Advanced Google services..., you only get the following OAuth Scopes added -

You can view these by navigating to File > Project properties > Scopes.

However, when you try the API from the documentation link, under the Credentials > Google OAuth 2.0 tab, it shows 4 more completely different OAuth scopes; those are as follows -

You need to add all 8 of these manually in your Apps script manifest file. To do that, navigate to View & check the Show manifest file. There you need to add this code, perhaps below dependencies -

"oauthScopes": [
  "https://www.googleapis.com/auth/classroom.courses",
  "https://www.googleapis.com/auth/classroom.coursework.me.readonly",
  "https://www.googleapis.com/auth/classroom.profile.emails",
  "https://www.googleapis.com/auth/classroom.profile.photos",
  "https://www.googleapis.com/auth/classroom.rosters",

  "https://www.googleapis.com/auth/classroom.coursework.me",
  "https://www.googleapis.com/auth/classroom.coursework.me.readonly",
  "https://www.googleapis.com/auth/classroom.coursework.students",
  "https://www.googleapis.com/auth/classroom.coursework.students.readonly"
],

Note1: Only adding the newer 4 will not do the trick as the script would assume only these and not the original 5 there were auto-populated when your script ran for the first time.

Note2: The blank line is simply to differentiate between the scopes that get generated automatically vs. the ones you need to add manually (its redundant).

My appsscript.json file looks like this; yours might differ -

{
  "timeZone": "Asia/Kolkata",
  "dependencies": {
    "enabledAdvancedServices": [{
      "userSymbol": "Classroom",
      "serviceId": "classroom",
      "version": "v1"
    }]
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/classroom.courses",
    "https://www.googleapis.com/auth/classroom.coursework.me.readonly",
    "https://www.googleapis.com/auth/classroom.profile.emails",
    "https://www.googleapis.com/auth/classroom.profile.photos",
    "https://www.googleapis.com/auth/classroom.rosters",

    "https://www.googleapis.com/auth/classroom.coursework.me",
    "https://www.googleapis.com/auth/classroom.coursework.me.readonly",
    "https://www.googleapis.com/auth/classroom.coursework.students",
    "https://www.googleapis.com/auth/classroom.coursework.students.readonly"
  ],
  "exceptionLogging": "STACKDRIVER"
}
Sourabh Choraria
  • 2,255
  • 25
  • 64
  • 2
    It is not necessary to manually add these missing scopes. The appropriate auth can be forced to prompt by including the following comment (inspired by the observation by @Tom Hinkle in [his answer](https://stackoverflow.com/a/46028983/1623277)): `// Classroom.Courses.CourseWork.create(courseId)` – zimady May 03 '20 at 20:26
  • the only one works for me. perhaps the former effort did something as well: https://stackoverflow.com/questions/38949318/google-sheets-api-returns-the-caller-does-not-have-permission-when-using-serve – Toma Apr 01 '21 at 18:47
2

I was getting this error repeatedly running the code as both a domain admin and as a teacher of the course I was testing with (i.e. I really should have had access).

In trying to ferret out the permissions issues, I tried making a call to Classroom.Courses.CourseWork.create, which triggered another authorization dialog that included additional permissions for accessing coursework. Even though my create call failed (I was still playing w/ the API and hadn't gotten the syntax right), the permissions it triggered were what I needed to get the course listing correct.

In short, here's the code that initially failed with the permission error you describe:

function getCoursework(id) {
  var resp = Classroom.Courses.CourseWork.list(id);
  work = resp.courseWork
  if (work && work.length > 0) {
    for (var i=0; i< work.length; i++) {
      piece = work[i]
      Logger.log('Work: %s (%s)',piece.title,JSON.stringify(piece));
    }
  }
}

That code did not trigger a permissions dialog, as it should have. However, once I ran the following (broken) code, I did get a permissions dialog, and then the above code worked:

function createCoursework (id) {
  Classroom.Courses.CourseWork.create(id,
    { // doesn't work but triggers permissions correctly
  "courseId": id,
  "title": 'foo',
  "description": 'desc',
    });
}
Tom Hinkle
  • 61
  • 7
  • Note that it is possible to trigger _all_ of the necessary scopes simply by including the create stub in a comment in the script: `// Classroom.Courses.CourseWork.create(courseId)` – zimady May 03 '20 at 20:18
0

As stated in this thread, make sure that the app script is associated with correct dev console project.

The script should be associated with the dev console project id that corresponds with OAuth 2.0 client ID used (this dev console project should also have "Apps Script Execution API" enabled).

To change the developer console project for an app script select the following menu item: Resources > Developer Console Project...

On this screen enter the project number for your dev console.

You must supply a valid OAuth token to use the API, and this requires a Developer Console Project.

Community
  • 1
  • 1
abielita
  • 13,147
  • 2
  • 17
  • 59
  • If I didn't have those things set correctly, wouldn't a call for the course list fail? It doesn't. I can get the course list and the student roster, just not the coursework list. I found this [thread](http://stackoverflow.com/questions/31845646/authorization-needed-for-classroom-profile-emails) which may be relevant, stating that the Classroom service prompts for a fixed set of scopes. That set doesn't include coursework.students. Does this mean I can't access coursework? – Joel White Mar 15 '17 at 19:03
  • I've edited the question to include links to previous threads. This [thread](http://stackoverflow.com/questions/31845646/authorization-needed-for-classroom-profile-emails) indicates that the scopes in an Apps Script for Classroom are fixed. Is there a workaround for this? – Joel White Mar 16 '17 at 21:19
0

I ahve the same issue - when running a Google Apps script add-on as a teacher of the project, the call to Courses.CourseWork.list works fine.

As soon as I switch to running the same script add-on as a student in the course, I get the 'The caller does not have permission' error.

This is not controllable by the developer of the add-on as beyond turning on the Classroom API, the scopes are not controllable by the developer.

The core issue is - code works for teachers of a course. Code fails for students of the course.

All this while the Classroom APi reference itself works fine. https://developers.google.com/classroom/reference/rest/v1/courses.courseWork/list

This is most likely a bug - at the very least, nothing to do with the generic catch-all answer given by @abielita above.

I see this bug is old so I have little hopes of an answer but here's hoping.

The Fat Oracle
  • 646
  • 1
  • 8
  • 19