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



我有一个移动应用程序,我想从我的服务器在用户的谷歌日历上添加事件。我已经在iOS上添加了同意流,并从响应中获得了idToken。我还可以在客户端上使用getTokens获得accessToken。但是,我无法使用它们在服务器上获取适当的刷新令牌,以便我可以在稍后阶段调用日历 API。对于 Web 应用,它需要客户端密码。ios 客户端没有密钥,当我使用我的 Web 客户端 ID 和密钥时,我得到的权限不足:权限不足:请求的身份验证范围不足。

澄清一下,我的步骤是:

  1. 通过电话获得同意和idToken
  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

感谢您的帮助!

我最终要做的是使用 Web 客户端 ID 和密钥将身份验证流用于打开系统浏览器窗口的已安装应用程序。我使用指向我的服务器终结点的重定向 uri,在该终结点中,我使用 google-api 客户端获取具有提供代码的刷新和访问令牌。

反应原生代码:

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);

导轨代码:

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!

希望这对其他人有帮助。

因为你遵循了错误的流程。当您遵循已安装的应用程序流时,您可以从移动端访问access_tokenreferesh_token,但它在服务器端不起作用。因此,您需要追求网络流,您的移动应用程序只是调出谷歌oauth2授权页面并向服务器端执行发送授权代码,这是服务器端的责任,使用在谷歌开发人员控制台中创建的Web 流应用程序凭据将该代码交换给access_tokenrefresh_token

在这里,我发布了一个更全面的答案来解决这个问题。

最新更新