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

macOS下Ruby客户端访问Google Workspace Sheet OAuth授权失败(不支持grant_type)

解决Signet::AuthorizationError: unsupported_grant_type错误

你的问题出在手动实例化UserRefreshCredentials的方式不正确,缺少关键参数,而且没有利用UserAuthorizer提供的标准化流程处理授权码交换。下面是具体修复步骤和完整代码:

核心问题分析

直接创建Google::Auth::UserRefreshCredentials时,你只传入了client_id.id,但未传递client_secret,也没有正确初始化授权流程所需的grant_type相关参数。正确做法是通过UserAuthorizer获取或创建凭证,它会自动处理这些细节。

修复后的完整代码

require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'launchy'
require 'webrick'

# Configuration
secrets = ENV['HOME'] + '/.secrets'
credentials_file = secrets + '/google_workspace_client_secret.json'
token_store_file = secrets + '/google_workspace_token.yaml'

# Authorization
scopes = ['https://www.googleapis.com/auth/spreadsheets']
client_id = Google::Auth::ClientId.from_file(credentials_file)
token_store = Google::Auth::Stores::FileTokenStore.new(file: token_store_file)
authorizer = Google::Auth::UserAuthorizer.new(client_id, scopes, token_store)

# 关键修改:通过authorizer获取凭证,替代手动实例化
user_id = 'default' # 多用户场景可设置不同标识
user_credentials = authorizer.get_credentials(user_id)

if user_credentials.nil?
  auth_uri = authorizer.get_authorization_url(
    access_type: 'offline',
    prompt: 'select_account consent',
    redirect_uri: 'http://localhost:8080'
  )

  Launchy.open(auth_uri)

  # 简化WEBrick配置,无需指定DocumentRoot
  server = WEBrick::HTTPServer.new Port: 8080
  server.mount_proc '/' do |req, res|
    code = req.query['code']

    if code.nil?
      res.status = 200
      res['Content-Type'] = 'text/html'
      res.body = %(<html><body><h2>Authorization required</h2><p>Click <a href="#{auth_uri}">here</a> to authorize the application.</p></body></html>)
    else
      # 关键修改:用authorizer交换授权码并存储凭证
      user_credentials = authorizer.get_and_store_credentials_from_code(
        user_id: user_id,
        code: code,
        base_url: 'http://localhost:8080'
      )

      res.status = 200
      res['Content-Type'] = 'text/html'
      res.body = '<html><body><h2>Authorization successful!</h2></body></html>'

      # 授权成功后停止服务器
      Thread.new { sleep 1; server.shutdown }
    end
  end

  trap('INT') { server.shutdown }
  server.start
end

# 新增:Google Sheets API调用示例
require 'google/apis/sheets_v4'
sheets = Google::Apis::SheetsV4::SheetsService.new
sheets.authorization = user_credentials

# 测试更新表格
spreadsheet_id = '你的表格ID'
range = 'Sheet1!A1'
value_range = Google::Apis::SheetsV4::ValueRange.new(values: [['测试内容']])
sheets.update_spreadsheet_value(spreadsheet_id, range, value_range, value_input_option: 'RAW')

主要修改点

  • 用authorizer.get_credentials(user_id)替代手动创建凭证,自动从token store读取已有授权信息
  • 用authorizer.get_authorization_url生成授权链接,替代直接调用凭证类的方法
  • 用authorizer.get_and_store_credentials_from_code处理授权码交换,自动完成token获取和存储,避免手动设置code导致的grant_type错误
  • 修复WEBrick响应设置逻辑,原数组返回方式不符合WEBrick API要求
  • 添加服务器自动停止逻辑,授权成功后1秒关闭服务
  • 补充Sheets API更新示例,方便直接验证功能

额外注意事项

  • 确保google_workspace_client_secret.json是从Google Cloud控制台下载的OAuth 2.0桌面应用客户端ID
  • 首次授权后,token会自动保存到google_workspace_token.yaml,后续运行无需重复授权

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 11:58:20