Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Classroom Apps Script - CourseWork.list permission error

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.

like image 936
Joel White Avatar asked Sep 07 '25 20:09

Joel White


2 Answers

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 -

  • 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

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 -

  • 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

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"
}
like image 149
Sourabh Choraria Avatar answered Sep 09 '25 17:09

Sourabh Choraria


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',
    });
}
like image 23
Tom Hinkle Avatar answered Sep 09 '25 17:09

Tom Hinkle