Google Classroom createCourse API调用出现401认证错误求助
问题背景
已完成以下操作:
- 创建外部模式的新项目
- 启用Google Classroom API
- 设置OAuth内容界面及凭证(生成含OAuth Client ID的
credentials.json) - 在CodeIgniter中通过composer安装
google/apiclient:^2.0库
尝试使用如下CodeIgniter代码创建课程:
defined('BASEPATH') OR exit('No direct script access allowed'); require FCPATH . 'vendor/autoload.php'; use Google\Client; use Google\Service\Classroom; use Google\Service\Classroom\Course; use Google\Service\Exception; class Googleclassroom extends CI_Controller { function __construct() { parent::__construct(); } public function createCourse() { $client = new Google_Client(); $client->setApplicationName('Google Classroom API PHP '); $client->setScopes(Google_Service_Classroom::CLASSROOM_COURSES_READONLY); $client->setAuthConfig('credentials.json'); $client->setAccessType('offline'); $client->setPrompt('select_account consent'); $client->addScope("https://www.googleapis.com/auth/classroom.courses"); $service = new Classroom($client); $course = new Course([ 'name' => '10th Biology', 'section' => 'Period 2', 'descriptionHeading' => 'Welcome to 10th Grade Biology', 'description' => 'hi', 'room' => '301', 'ownerId' => 'me', 'courseState' => 'PROVISIONED' ]); $course = $service->courses->create($course); printf("Course created: %s (%s)\n", $course->name, $course->id); } }
访问http://baseUrl/Googleclassroom/createCourse时触发401认证错误:
An uncaught Exception was encountered
Type: Google_Service_Exception
Message: { "error": { "code": 401, "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.", "errors": [ { "message": "Invalid Credentials", "domain": "global", "reason": "authError", "location": "Authorization", "locationType": "header" } ], "status": "UNAUTHENTICATED" } }
解决方案
1. 补充OAuth授权流程,获取有效访问令牌
当前代码仅初始化了客户端,但未处理OAuth授权流程,没有获取到有效的访问令牌。需添加完整的授权逻辑:
public function createCourse() { $client = new Google_Client(); $client->setApplicationName('Google Classroom API PHP '); // 直接设置创建课程所需的权限,避免重复添加 $client->setScopes([Google_Service_Classroom::CLASSROOM_COURSES]); // 使用FCPATH确保凭证文件路径正确 $client->setAuthConfig(FCPATH . 'credentials.json'); $client->setAccessType('offline'); $client->setPrompt('select_account consent'); $tokenPath = FCPATH . 'token.json'; // 检查是否已有存储的令牌 if (file_exists($tokenPath)) { $accessToken = json_decode(file_get_contents($tokenPath), true); $client->setAccessToken($accessToken); } // 处理令牌过期情况 if ($client->isAccessTokenExpired()) { if ($client->getRefreshToken()) { // 刷新过期的令牌 $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); } else { // 无刷新令牌,引导用户授权 $authUrl = $client->createAuthUrl(); redirect($authUrl); } // 保存更新后的令牌 file_put_contents($tokenPath, json_encode($client->getAccessToken())); } $service = new Classroom($client); $course = new Course([ 'name' => '10th Biology', 'section' => 'Period 2', 'descriptionHeading' => 'Welcome to 10th Grade Biology', 'description' => 'hi', 'room' => '301', 'ownerId' => 'me', 'courseState' => 'PROVISIONED' ]); try { $course = $service->courses->create($course); printf("Course created: %s (%s)\n", $course->name, $course->id); } catch (Exception $e) { echo 'Error creating course: ' . $e->getMessage(); } } // 添加OAuth回调方法处理授权返回 public function oauth2callback() { $client = new Google_Client(); $client->setAuthConfig(FCPATH . 'credentials.json'); $client->setScopes([Google_Service_Classroom::CLASSROOM_COURSES]); $client->setAccessType('offline'); // 获取授权码并交换访问令牌 $authCode = $this->input->get('code'); $accessToken = $client->fetchAccessTokenWithAuthCode($authCode); $client->setAccessToken($accessToken); // 保存令牌到项目根目录 $tokenPath = FCPATH . 'token.json'; file_put_contents($tokenPath, json_encode($accessToken)); // 重定向回创建课程的方法 redirect('Googleclassroom/createCourse'); }
2. 修正权限配置
原代码先设置只读权限CLASSROOM_COURSES_READONLY,再添加创建权限,可能导致权限冲突。直接设置CLASSROOM_COURSES权限即可,无需重复添加。
3. 确保凭证文件路径正确
使用CodeIgniter的FCPATH常量指定credentials.json的完整路径,避免因相对路径问题无法读取文件。
4. 配置OAuth回调地址
在Google Cloud控制台的OAuth 2.0凭证设置中,添加回调地址http://baseUrl/Googleclassroom/oauth2callback,确保授权流程能正常完成。
5. 令牌存储说明
首次访问createCourse方法时,会自动跳转到Google授权页面,用户完成授权后,系统会将令牌保存为token.json到项目根目录,后续请求会自动使用该令牌进行认证,无需重复授权。
内容的提问来源于stack exchange,提问作者Rakesh Hiray

