Google API OAuth 2.0 在移动设备上获得用户权限,在服务器端使用 API

Google API OAuth 2.0 get user permission on mobile device, use on server side API

我有一个移动应用程序,我想从我的服务器向用户的 google 日历添加活动。我已经在 iOs 上添加了同意流程,并且我从响应中获得了一个 idToken。我还可以在客户端上使用 getTokens 获得 accessToken。但是我无法使用这些来在服务器上获得适当的刷新令牌,因此我可以在稍后阶段调用日历 API。对于 Web 应用程序,它需要一个客户端密码。 ios 客户端没有密码,当我使用我的 Web 客户端 ID 和密码时,我得到 insufficientPermissions: Insufficient Permission: Request had insufficient authentication scopes. .

为了澄清,我的步骤是:

  1. 获得同意并 idToken phone
  2. 发送idToken到服务器
  3. 使用 idToken 在服务器上获取刷新令牌(这就是问题所在
  4. 使用刷新令牌在用户的日历上创建事件

这是我的 ios React Native 代码:

signInWithGoogle() {
    GoogleSignin.configure({scopes: ['https://www.googleapis.com/auth/calendar', 'https://www.googleapis.com/auth/calendar.events']});

    GoogleSignin.signIn()
    .then(result => {
      // idToken
      console.log(result);
      GoogleSignin.getTokens()
      .then(tokens => {
        //this gets me an accessToken
        console.log(tokens);
      })
    }).catch(error => {
      console.log('google auth error: ', error);
    });
  }

我的服务器端代码:

secrets = Google::APIClient::ClientSecrets.new({
      "web" => {
        "refresh_token" => ENV['GOOGLE_REFRESH_TOKEN'],
        "client_id" => ENV["GOOGLE_CLIENT_ID"],
        "client_secret" => ENV["GOOGLE_CLIENT_SECRET"]
      }
    })
auth_code = idToken_from_client
auth_client = secrets.to_authorization
auth_client.update!(scope: 'https://www.googleapis.com/auth/calendar.events')
auth_client.code = auth_code
auth_client.fetch_access_token!

我知道服务器代码没有意义,因为我已经有一个访问令牌,但是我需要一个刷新令牌。只要用户使用应用程序并且访问令牌过期,我就需要为用户创建事件。这就是他们推荐的在服务器端授权文档中获取刷新令牌的方法:https://developers.google.com/identity/protocols/oauth2/web-server#exchange-authorization-code

感谢您的帮助!

我最后做的是使用 installed apps opening a system browser window, using the web client id and secret. I use the redirect uri pointing to my server endpoint where I use the google-api-client 的身份验证流程,使用提供的代码获取刷新和访问令牌。

ReactNative 代码:

const scope = 'scope=the_google_scope';
const redirect = 'redirect_uri=redirect_for_google_auth'; // Your serverside endpoint
const url = `https://accounts.google.com/o/oauth2/v2/auth?${scope}&prompt=consent&access_type=offline&response_type=code&${redirect}&client_id=${googleClientID}`

Linking.openURL(url);

Rails代码:

require "google/api_client/client_secrets.rb"
...
secrets = Google::APIClient::ClientSecrets.new({
      web: {
        client_id: googleClientID, # Same one used on the client
        client_secret: googleClientSecret,
        grant_type: "authorization_code",
        redirect_uri: "redirect_for_google_auth"
      }
    })
auth_client = secrets.to_authorization
auth_client.code = code_retrieved_from_google
auth_result = auth_client.fetch_access_token!

希望这对遇到这种情况的其他人有所帮助。