调用Classroom API registrations().create()返回无权限错误求助
问题背景
已完成以下配置,但调用Classroom API的registrations().create()接口时仍返回403权限错误:
- 为Google Workspace配置了域级委托权限
- 给
classroom-notifications@system.gserviceaccount.com授予了Pub/Sub主题的IAM权限 - 使用超级管理员账号
no-reply@nemk.ukr.education作为委托账号
错误信息:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://classroom.googleapis.com/v1/registrations?alt=json returned "The caller does not have permission". Details: "The caller does not have permission">
用户提供的代码:
from googleapiclient.discovery import build from google.oauth2.service_account import Credentials SCOPES = ['https://www.googleapis.com/auth/classroom.push-notifications', 'https://www.googleapis.com/auth/classroom.rosters'] body = { "feed": { "feedType": "COURSE_WORK_CHANGES", "courseWorkChangesInfo": { "courseId": (courseId) }, }, "cloudPubsubTopic": { "topicName": "projects/(my-project)/topics/coursework-notifications" } } def main(): service_account = 'secrets.json' credentials = Credentials.from_service_account_file( service_account, scopes=SCOPES) delegate = credentials.with_subject("no-reply@nemk.ukr.education") service = build('classroom', 'v1', credentials=delegate) try: result = service.registrations().create(body=body).execute() print(result) except Exception as error: print(error.content) print(dir(error)) if __name__ == '__main__': main()
排查与解决步骤
检查域级委托的API范围配置
登录Google Admin控制台,进入安全 > API控制 > 域级委托,确认已为目标服务账号添加以下完整OAuth2范围:https://www.googleapis.com/auth/classroom.push-notifications、https://www.googleapis.com/auth/classroom.rosters
注意范围不能有拼写错误,配置保存后需等待15-30分钟生效。验证Pub/Sub主题的IAM权限
除了给classroom-notifications@system.gserviceaccount.com添加roles/pubsub.publisher权限,还要确认代码中使用的服务账号(对应secrets.json的账号)拥有roles/pubsub.admin或roles/pubsub.editor权限——创建注册时需要验证主题所有权。同时检查权限列表,确保没有被其他规则覆盖。确认委托账号的实际权限
尽管no-reply@nemk.ukr.education是超级管理员,仍需确认:- 该账号未被限制API访问(Admin控制台安全 > API权限中未禁用Classroom API)
- 账号能正常访问目标课程的作业资源(直接登录Classroom网页端验证)
修正代码参数问题
- 移除
courseId值的多余括号,改为"courseId": courseId - 将
(my-project)替换为实际的Google Cloud项目ID,确保topicName完全正确
- 移除
验证服务账号的域级委托状态
登录Google Cloud控制台,找到目标服务账号,在详情页的“高级设置”中确认域级委托已开启,且该账号已在Google Admin控制台中被标记为可信OAuth客户端。
调整后的示例代码
from googleapiclient.discovery import build from google.oauth2.service_account import Credentials SCOPES = [ 'https://www.googleapis.com/auth/classroom.push-notifications', 'https://www.googleapis.com/auth/classroom.rosters' ] # 替换为实际的课程ID和Pub/Sub主题名称 COURSE_ID = "your-actual-course-id" PUBSUB_TOPIC = "projects/your-project-id/topics/coursework-notifications" body = { "feed": { "feedType": "COURSE_WORK_CHANGES", "courseWorkChangesInfo": { "courseId": COURSE_ID } }, "cloudPubsubTopic": { "topicName": PUBSUB_TOPIC } } def main(): service_account_path = 'secrets.json' credentials = Credentials.from_service_account_file( service_account_path, scopes=SCOPES ) delegated_credentials = credentials.with_subject("no-reply@nemk.ukr.education") service = build('classroom', 'v1', credentials=delegated_credentials) try: result = service.registrations().create(body=body).execute() print("注册成功:", result) except Exception as error: print("错误详情:", error.content) if __name__ == '__main__': main()
内容的提问来源于stack exchange,提问作者Azazel

