Google cloud platform 使用GoogleAuth库ruby和GoogleAPI ruby客户端的三条腿OAuth和一次性代码流

Google cloud platform 使用GoogleAuth库ruby和GoogleAPI ruby客户端的三条腿OAuth和一次性代码流,google-cloud-platform,google-oauth,google-signin,google-api-ruby-client,google-auth-library-ruby,Google Cloud Platform,Google Oauth,Google Signin,Google Api Ruby Client,Google Auth Library Ruby,快速概述:我有一个ruby应用程序,每晚运行,并使用用户的谷歌日历做一些事情。用户已通过单独的react应用程序授予访问权限。我无法让ruby应用程序使用react应用程序的授权代码访问用户的日历 详细信息:我有一个React前端,可以使用gapi登录用户,然后将用户登录到Firebase。下面是我如何配置gapi obj的: this.auth2 = await loadAuth2WithProps({ apiKey: config.apiKey, // from firebas

快速概述:我有一个ruby应用程序,每晚运行,并使用用户的谷歌日历做一些事情。用户已通过单独的react应用程序授予访问权限。我无法让ruby应用程序使用react应用程序的授权代码访问用户的日历

详细信息:我有一个React前端,可以使用gapi登录用户,然后将用户登录到Firebase。下面是我如何配置gapi obj的:

this.auth2 = await loadAuth2WithProps({
  apiKey: config.apiKey,      // from firebase
  clientId: config.clientId,  // from gcp
  // ....
  access_type: "offline",     // so we get get authorization code
})
这里是登录:

doSignInWithGoogle =  async () => {
  const googleUser = await this.auth2.signIn();
  const token = googleUser.getAuthResponse().id_token;
  const credential = app.auth.GoogleAuthProvider.credential(token);
  return this.auth.signInWithCredential(credential);
};
用户的下一步是授予应用程序对其日历的脱机访问权限:

doConnectGoogleCalendar =  async () => {
  const params = {scope:scopes};
  const result = await this.auth2.grantOfflineAccess(params);
  console.log(result.code); // logs: "4/ygFsjdK....."
};
此时,前端具有可传递给服务器端应用程序以交换访问和刷新令牌的授权代码。我还没有找到一种使用用户提供的身份验证代码调用可用作用域的好方法。以下是我配置oauth客户端的方式:

auth_client = Google::APIClient::ClientSecrets.load(
  File.join(Rails.root,'config','client_secrets.json') // downloaded from GCP
).to_authorization
^我在后端使用与前端相同的GCP凭据。它是“OAuth 2.0客户端ID”类型的凭据我不确定这是否是一种好的做法。此外,我是否需要定义与在前端上相同的配置(如访问类型和范围)?。

接下来,我按照文档所说的去做(单击Ruby):

在设置一个单独的后端应用程序来处理对用户授权范围的脱机访问时,我是否缺少一些东西?关于这些库有很多不同的信息,但我还不能把它们提炼成有用的东西

更新
我找到了这个描述“”的页面,我在其他任何地方都找不到它,这是我看过的所有文档。它确实回答了我上面的一个小问题:是的,您可以在后端使用与web应用程序相同的客户机机密。(请参阅底部的完整示例,他们就是这样做的)。我会进一步探索,看看我的大问题能否解决。还将更新标题以包含一次性代码流。

在大量挖掘代码示例和源代码之后,我有了一个干净的工作解决方案。一旦我在“更新”中找到了该页面,它就让我发现
ClientSecrets
我做事的方式有利于该项目。我很高兴我找到了它,因为它似乎是一个更完整的解决方案,因为它可以为您处理所有的令牌管理。下面是设置所有内容的代码:

def authorizer
    client_secrets_path = File.join(Rails.root,'config','client_secrets.json')
    client_id = Google::Auth::ClientId.from_file(client_secrets_path)
    scope = [Google::Apis::CalendarV3::AUTH_CALENDAR_READONLY]
    redis = Redis.new(url: Rails.application.secrets.redis_url)
    token_store = Google::Auth::Stores::RedisTokenStore.new(redis: redis)
    Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store, "postmessage")
end
然后这就是我如何使用授权码的方法:

def exchange_for_token(user_id,auth_code) 
    credentials_opts = {user_id:user_id,code:auth_code}
    credentials = authorizer.get_and_store_credentials_from_code(credentials_opts)
end
调用该方法后,库将在Redis中存储交换的令牌(您可以配置存储位置),以便以后使用,如下所示:

def run_job(user_id)
    credentials = authorizer.get_credentials(user_id)
    service = Google::Apis::CalendarV3::CalendarService.new
    service.authorization = credentials
    calendar_list = service.list_calendar_lists.items
    # ... do more things ...
end

信息太多,很难区分适用于每种情况的信息。希望这能帮助其他陷入“一次性代码流”困境的人,这样他们就不会在办公桌上浪费时间。

一个奇怪的错误是,这个未记录的“postmessage”替换了重定向url。。。在这里的答案中找到了宝石:-boooooooo
def run_job(user_id)
    credentials = authorizer.get_credentials(user_id)
    service = Google::Apis::CalendarV3::CalendarService.new
    service.authorization = credentials
    calendar_list = service.list_calendar_lists.items
    # ... do more things ...
end