You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Apps Script API调用Google Sheets函数时遇401未授权错误求助

在Ruby on Rails中使用Apps Script API时遭遇401 Unauthorized错误的解决建议

问题背景

尝试在Ruby on Rails应用中调用Google Apps Script API执行Google Sheets函数,因API不支持服务账号,改用OAuth 2.0认证,但调用run_script时始终返回401未授权错误。

现有代码

require 'google/apis/drive_v3'
require 'sinatra'
require 'googleauth'
require 'googleauth/stores/redis_token_store'

client_id = Google::Auth::ClientId.from_file('lib/get_property_data/client_secret.json')
scope = ['https://www.googleapis.com/auth/spreadsheets']
token_store=  Google::Auth::Stores::RedisTokenStore.new(redis: Redis.new)
authorizer = Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, '/oauth2callback')

service = Google::Apis::ScriptV1::ScriptService.new
service.client_options.application_name = 'Application name'
service.authorization = authorizer

request = Google::Apis::ScriptV1::ExecutionRequest.new(function: 'testFunction', parameters: ['sheet_id'])
script_id = 'xxxxxxx'

response  = service.run_script(script_id, request)

错误信息

Caught error Unauthorized
Error - #<Google::Apis::AuthorizationError: Unauthorized status_code: 401 header: #<HTTP::Message::Headers:0x00007f806c517978 @http_version="1.1", @body_size=0, @chunked=false, @request_method="POST", @request_uri=#<Addressable::URI:0x3fc03926f794 URI:https://script.googleapis.com/v1/scripts/1BrWLyFp4L0Q-00sZekntFTsZzed_4TLesPQYUSDWx-AbRe4EVEGd5-DW:run?>, @request_query=nil, @request_absolute_uri=nil, @status_code=401, @reason_phrase="Unauthorized", @body_type=nil, @body_charset=nil, @body_date=nil, @body_encoding=#<Encoding:UTF-8>, @is_request=false, @header_item=[["WWW-Authenticate", "Bearer realm=\"https://accounts.google.com/\""], ["Vary", "Origin"], ["Vary", "X-Origin"], ["Vary", "Referer"], ["Content-Type", "application/json; charset=UTF-8"], ["Content-Encoding", "gzip"], ["Date", "Wed, 20 Sep 2023 12:27:41 GMT"], ["Server", "ESF"], ["Cache-Control", "private"], ["X-XSS-Protection", "0"], ["X-Frame-Options", "SAMEORIGIN"], ["X-Content-Type-Options", "nosniff"], ["Alt-Svc", "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"], ["Transfer-Encoding", "chunked"]], @dumped=false> body: "{
  \"error\": {
    \"code\": 401,
    \"message\": \"Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential.\",
    \"errors\": [
      {
        \"message\": \"Login Required.\",
        \"domain\": \"global\",
        \"reason\": \"required\",
        \"location\": \"Authorization\",
        \"locationType\": \"header\"
      }
    ],
    \"status\": \"UNAUTHENTICATED\",
    \"details\": [
      {
        \"@type\": \"type.googleapis.com/google.rpc.ErrorInfo\",
        \"reason\": \"CREDENTIALS_MISSING\",
        \"domain\": \"googleapis.com\",
        \"metadata\": {
          \"service\": \"script.googleapis.com\",
          \"method\": \"google.apps.script.v1.ScriptExecution.Execute\"
        }
      }
    ]
  }
}\n">

Retrying after authentication failure
Traceback (most recent call last):
        1: from (irb):37
Google::Apis::AuthorizationError (Unauthorized)

解决建议

1. 修正OAuth权限范围

当前仅请求了spreadsheets权限,但调用Apps Script API需要额外添加脚本相关权限,替换scope为:

scope = [
  'https://www.googleapis.com/auth/spreadsheets',
  'https://www.googleapis.com/auth/script.projects',
  'https://www.googleapis.com/auth/script.execution'
]

2. 完整触发OAuth授权流程

WebUserAuthorizer不能直接绑定到service后调用接口,必须先引导用户完成授权获取有效令牌:

  • 添加授权回调路由:
# 引导用户授权的路由
get '/authorize' do
  user_id = session[:user_id] # 替换为实际用户标识,比如当前登录用户ID
  redirect authorizer.get_authorization_url(user_id: user_id, request: request)
end

# OAuth回调处理路由
get '/oauth2callback' do
  user_id = session[:user_id]
  authorizer.get_and_store_credentials_from_code(
    user_id: user_id, code: params[:code], request: request
  )
  redirect '/' # 授权完成后跳转至业务页面
end
  • 调用API前验证令牌:
user_id = session[:user_id]
credentials = authorizer.get_credentials(user_id, request)

if credentials.nil?
  redirect '/authorize' # 无有效令牌则引导授权
else
  # 检查令牌是否过期,过期则刷新
  credentials.refresh! if credentials.expired?
  service.authorization = credentials
  # 执行API调用
  response = service.run_script(script_id, request)
end

3. 检查Google Cloud项目配置

  • 确认项目中已启用Apps Script API和Google Sheets API
  • 验证OAuth客户端ID类型为「Web应用」,且回调地址与代码中的/oauth2callback完全一致
  • 若为外部应用,需在OAuth同意屏幕中添加测试用户

4. 验证令牌有效性

可以通过以下代码检查令牌状态:

puts "Access Token: #{credentials.access_token}"
puts "Token Expired: #{credentials.expired?}"

内容的提问来源于stack exchange,提问作者sajid nawaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:41:01