通过 Google 课堂 API 创建教师时请求的身份验证范围错误不足
Request had insufficient authentication scopes error when creating teacher through Google Classroom API
我正在尝试通过 google 教室 api 为学生创建作业。但是,我了解到管理员不能这样做,只有教师才能这样做。因此,在我们的代码中,在创建新课程后,我们将设置教师的电子邮件,这与管理员的电子邮件相同。但是,创建教师时代码失败。它说 请求的身份验证范围不足 。我尝试添加不同的额外范围,但我一直卡在这条错误消息上。
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;
}
}
完整代码如下:
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("%s\n", 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();
}
}
谢谢。
更新
根据@DaImTo'answer,添加这两个额外的配置文件修复了原来的错误。
ClassroomScopes.CLASSROOM_PROFILE_EMAILS,
ClassroomScopes.CLASSROOM_PROFILE_PHOTOS,
但是,我们仍然收到“调用者没有权限”的错误消息。
方法corses.create要求授权用户必须同意以下范围。
方法courses.teachers.create 需要以下范围之一
现在,如果我们查看您的代码,您似乎正在使用以下范围
List<String> SCOPES =
Arrays.asList(ClassroomScopes.CLASSROOM_COURSES,
ClassroomScopes.CLASSROOM_COURSEWORK_STUDENTS,
ClassroomScopes.CLASSROOM_COURSEWORK_ME,
ClassroomScopes.CLASSROOM_ROSTERS);
这应该足以确保您可以访问。但是,您似乎也在使用 CREDENTIALS_FILE_PATH,这是存储用户同意的地方。现在,如果您 运行 您的应用程序曾经请求用户访问并且用户同意了。然后该用户的凭据将存储在文件中。如果您随后更改了代码中的范围,则代码仍在使用旧范围从 CREDENTIALS_FILE_PATH 读取。
您需要强制您的应用程序再次请求用户的访问权限,并且这次同意适当的范围。
有两种方法可以做到这一点。删除CREDENTIALS_FILE_PATH
中的文件
其名称中包含“用户”。
或在您的这行代码中将“用户”更改为其他内容。
AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); change
我正在尝试通过 google 教室 api 为学生创建作业。但是,我了解到管理员不能这样做,只有教师才能这样做。因此,在我们的代码中,在创建新课程后,我们将设置教师的电子邮件,这与管理员的电子邮件相同。但是,创建教师时代码失败。它说 请求的身份验证范围不足 。我尝试添加不同的额外范围,但我一直卡在这条错误消息上。
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;
}
}
完整代码如下:
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("%s\n", 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();
}
}
谢谢。
更新
根据@DaImTo'answer,添加这两个额外的配置文件修复了原来的错误。 ClassroomScopes.CLASSROOM_PROFILE_EMAILS, ClassroomScopes.CLASSROOM_PROFILE_PHOTOS,
但是,我们仍然收到“调用者没有权限”的错误消息。
方法corses.create要求授权用户必须同意以下范围。
方法courses.teachers.create 需要以下范围之一
现在,如果我们查看您的代码,您似乎正在使用以下范围
List<String> SCOPES =
Arrays.asList(ClassroomScopes.CLASSROOM_COURSES,
ClassroomScopes.CLASSROOM_COURSEWORK_STUDENTS,
ClassroomScopes.CLASSROOM_COURSEWORK_ME,
ClassroomScopes.CLASSROOM_ROSTERS);
这应该足以确保您可以访问。但是,您似乎也在使用 CREDENTIALS_FILE_PATH,这是存储用户同意的地方。现在,如果您 运行 您的应用程序曾经请求用户访问并且用户同意了。然后该用户的凭据将存储在文件中。如果您随后更改了代码中的范围,则代码仍在使用旧范围从 CREDENTIALS_FILE_PATH 读取。
您需要强制您的应用程序再次请求用户的访问权限,并且这次同意适当的范围。
有两种方法可以做到这一点。删除CREDENTIALS_FILE_PATH
中的文件
其名称中包含“用户”。
或在您的这行代码中将“用户”更改为其他内容。
AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); change