macOS下Ruby客户端访问Google Workspace Sheet OAuth授权失败(不支持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
相关产品推荐
相关产品推荐

