使用Google Drive API上传文件遇iam.serviceAccounts.getAccessToken权限拒绝问题
问题:使用Google Drive API(C# SDK)服务账号上传时遇到权限错误“iam.serviceAccounts.getAccessToken”被拒绝
我尝试用Google Drive API的C# SDK上传文件,因为是后台服务,所以用服务账号执行上传,但碰到错误:Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist)。
我已经给项目配置了以下角色:
- Service Account Token Creator
- Service Account User
- 包含
iam.serviceAccounts.getAccessToken权限的自定义角色
生成本地JSON凭证的命令
gcloud auth application-default login --project=myprojectid --impersonate-service-account <svcacctname>@<application id>.iam.gserviceaccount.com --scopes="openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/sqlservice.login,https://www.googleapis.com/auth/drive
简化后的C#上传代码
using (var stream = new FileStream(@"C:\Users\myname\AppData\Roaming\gcloud\application_default_credentials.json", FileMode.Open, FileAccess.Read)) { var credentials = GoogleCredential.FromStream(stream); if (credentials.IsCreateScopedRequired) { credentials = credentials.CreateScoped(new string[] { DriveService.Scope.Drive }); } var service = new DriveService(new BaseClientService.Initializer() { HttpClientInitializer = credentials, ApplicationName = "myappid", }); FilesResource.CreateMediaUpload request; // Create a new file on drive. using (var stream = new FileStream(localFileName, FileMode.Open)) { // Create a new file, with metadata and stream. request = service.Files.Create( fileMetadata, stream, "audio/mp3"); request.Fields = "id"; IUploadProgress prog = request.Upload(); if (prog.Exception != null) { // code arrives here Console.WriteLine(prog.Exception.Message); } else { Console.WriteLine(request.ResponseBody); } }
异常响应
Error:"{ "error": { "code": 403, "message": "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).", "errors": [ { "message": "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist).", "domain": "global", "reason": "forbidden" } ], "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "IAM_PERMISSION_DENIED", "domain": "iam.googleapis.com", "metadata": { "permission": "iam.serviceAccounts.getAccessToken" } } ] } } ", Description:"", Uri:""
解决方案
1. 修正权限授予对象
iam.serviceAccounts.getAccessToken权限需要授予给执行gcloud命令的用户账号,而非服务账号本身。具体操作:
- 进入Google Cloud控制台的IAM & Admin > IAM页面
- 找到你用来登录gcloud的用户账号
- 点击编辑,添加角色 > Service Accounts > Service Account Token Creator,并将角色作用域指定为目标服务账号(而非整个项目)
2. 修复gcloud命令语法错误
原命令末尾缺少闭合双引号,导致作用域参数不完整,修正后的命令:
gcloud auth application-default login --project=myprojectid --impersonate-service-account <svcacctname>@<application id>.iam.gserviceaccount.com --scopes="openid,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/sqlservice.login,https://www.googleapis.com/auth/drive"
3. 确认Drive API配置
- 检查项目是否已启用Google Drive API:进入APIs & Services > Library搜索并启用
- 若上传到共享文件夹,需将服务账号邮箱添加为文件夹共享成员,授予编辑权限
4. 验证凭证有效性
重新生成凭证后,执行以下命令验证是否能获取有效令牌:
gcloud auth application-default print-access-token --impersonate-service-account <svcacctname>@<application id>.iam.gserviceaccount.com
返回有效令牌则说明凭证配置正确,仍报错则回到步骤1检查权限。
内容的提问来源于stack exchange,提问作者Mike Marshall
相关产品推荐
相关产品推荐

