Skip to content
Advertisement

Request had insufficient authentication scopes error when creating teacher through Google Classroom API

I’m trying to create assignments for students through the google classroom api. However, I’ve learned admins can not do that, only teachers. So in our code, after creating a new course we’re then setting the teacher’s email, which is the same as for the admin. However, the code fails when creating the teacher. It says the request had insufficient authentication scopes. I’ve tried to add different extra scopes but I’m stuck on this error message.

private static final List<String> SCOPES = 
 Arrays.asList(ClassroomScopes.CLASSROOM_COURSES, 
 ClassroomScopes.CLASSROOM_COURSEWORK_STUDENTS, 
 ClassroomScopes.CLASSROOM_COURSEWORK_ME, 
 ClassroomScopes.CLASSROOM_ROSTERS);


    Course course = new Course()
            .setName("10th Grade Biology")
            .setSection("Period 2")
            .setDescriptionHeading("Welcome to 10th Grade Biology")
            .setDescription("We'll be learning about about the structure of living creatures "
                    + "from a combination of textbooks, guest lectures, and lab work. Expect "
                    + "to be excited!")
            .setRoom("301")
            .setOwnerId("me")
            .setCourseState("PROVISIONED");

    course = service.courses().create(course).execute();
    System.out.printf("Course created: %s (%s)n", course.getName(), course.getId());


    String courseId = course.getId();
    String teacherEmail = "admin@gmail.com";
    Teacher teacher = new Teacher().setUserId(teacherEmail);
    try {
        teacher = service.courses().teachers().create(courseId, teacher).execute();
        System.out.printf("User '%s' was added as a teacher to the course with ID '%s'.n",
                teacher.getProfile().getName().getFullName(), courseId);
    } catch (GoogleJsonResponseException e) {
        GoogleJsonError error = e.getDetails();
        if (error.getCode() == 409) {
            System.out.printf("User '%s' is already a member of this course.n", teacherEmail);
        } else {
            throw e;
        }
    }

enter image description here

Here is the full code:

public class ClassroomQuickstart {
private static final String APPLICATION_NAME = "Google Classroom API Java Quickstart";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";


private static final List<String> SCOPES = Arrays.asList(ClassroomScopes.CLASSROOM_COURSES, ClassroomScopes.CLASSROOM_COURSEWORK_STUDENTS, ClassroomScopes.CLASSROOM_COURSEWORK_ME, ClassroomScopes.CLASSROOM_ROSTERS);


private static final String CREDENTIALS_FILE_PATH = "/credentials.json";


private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException {
    // Load client secrets.
    InputStream in = ClassroomQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
    if (in == null) {
        throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
    }
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));

    // Build flow and trigger user authorization request.
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
            .setAccessType("offline")
            .build();
    LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
    return new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
}


 public static void main(String... args) throws IOException, 
   GeneralSecurityException {
    // Build a new authorized API client service.
    final NetHttpTransport HTTP_TRANSPORT = 
   GoogleNetHttpTransport.newTrustedTransport();
    Classroom service = new Classroom.Builder(HTTP_TRANSPORT, JSON_FACTORY, 
   getCredentials(HTTP_TRANSPORT))
            .setApplicationName(APPLICATION_NAME)
            .build();

    // List the first 10 courses that the user has access to.
    ListCoursesResponse response = service.courses().list()
            .setPageSize(10)
            .execute();
    List<Course> courses = response.getCourses();
    if (courses == null || courses.size() == 0) {
        System.out.println("No courses found.");
    } else {
        System.out.println("Courses:");
        for (Course course : courses) {
            System.out.printf("%sn", course.getName());
        }
    }


    Course course = new Course()
            .setName("10th Grade Biology")
            .setSection("Period 2")
            .setDescriptionHeading("Welcome to 10th Grade Biology")
            .setDescription("We'll be learning about about the structure of living creatures "
                    + "from a combination of textbooks, guest lectures, and lab work. Expect "
                    + "to be excited!")
            .setRoom("301")
            .setOwnerId("me")
            .setCourseState("PROVISIONED");

    course = service.courses().create(course).execute();
    System.out.printf("Course created: %s (%s)n", course.getName(), course.getId());


    String courseId = course.getId();
    String teacherEmail = "admin@gmail.com";
    Teacher teacher = new Teacher().setUserId(teacherEmail);
    try {
        teacher = service.courses().teachers().create(courseId, teacher).execute();
        System.out.printf("User '%s' was added as a teacher to the course with ID '%s'.n",
                teacher.getProfile().getName().getFullName(), courseId);
    } catch (GoogleJsonResponseException e) {
        GoogleJsonError error = e.getDetails();
        if (error.getCode() == 409) {
            System.out.printf("User '%s' is already a member of this course.n", teacherEmail);
        } else {
            throw e;
        }
    }


   
//        CourseWork courseWork = new CourseWork()
//         .setCourseId(course.getId())
//          .setTitle("title")
//          .setWorkType("ASSIGNMENT")
//           .setDescription("desc");

//        service.courses().courseWork().create(course.getId(), courseWork).execute();

}

}

Thank you.

UPDATE

As per @DaImTo’answer, adding these two extra profiles fixed the original error. ClassroomScopes.CLASSROOM_PROFILE_EMAILS, ClassroomScopes.CLASSROOM_PROFILE_PHOTOS,

However, we’re still getting a “The caller does not have permission” error message.

Advertisement

Answer

The method corses.create requires that the authorized user must have consented with the following scope.

enter image description here

the method courses.teachers.create requires one of the following scopes

enter image description here

Now if we look at your code you appear to be using the following scopes

List<String> SCOPES = 
 Arrays.asList(ClassroomScopes.CLASSROOM_COURSES, 
 ClassroomScopes.CLASSROOM_COURSEWORK_STUDENTS, 
 ClassroomScopes.CLASSROOM_COURSEWORK_ME, 
 ClassroomScopes.CLASSROOM_ROSTERS);

which should be enough to ensure that you have access. However you also apear to be using CREDENTIALS_FILE_PATH which is where the users consent will be stored. Now if you ran your application once and requested access of the user and the user consented to it. Then the credetinals for that user would be stored in the file. If you then changed the scopes in your code the code is still reading from CREDENTIALS_FILE_PATH with the old scopes.

You need to force your application to request access of the user again and this time consent to the proper scopes.

There are two ways to do that. Delete the file in CREDENTIALS_FILE_PATH
which contains “user” in its name.

or change “user” to something else in this line of your code.

 AuthorizationCodeInstalledApp(flow, receiver).authorize("user");  change 
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement