我无法从 Google 获取一次性授权码。我正在尝试从 Android 客户端获取授权代码,以便可以将其发送到我的 Rails 后端(Web 客户端)。
在我的 Google Cloud Developer Console 中,我有一个具有两个客户端 ID 的应用程序:
Web 应用程序的客户端 ID(用于我的 rails 后端)
Android 应用程序的客户端 ID(用于我的 android 客户端)。使用的 SHA1 来自 ~/.android/debug.keystore
假设 Web 应用程序客户端 ID 是12345.apps.googleusercontent.com
假设 Android 客户端 ID 是67890.apps.googleusercontent.com
这是我的一些代码:
private final static String WEB_CLIENT_ID = "12345.apps.googleusercontent.com";
private final static String GOOGLE_CALENDAR_API_SCOPE = "audience:server:client_id:" + WEB_CLIENT_ID;
private void getAndUseAuthToken(final String email) {
AsyncTask task = new AsyncTask<String, Void, String>() {
@Override
protected String doInBackground(String... emails) {
try {
return GoogleAuthUtil.getToken(AddExternalCalendarsActivity.this, emails[0], GOOGLE_CALENDAR_API_SCOPE);
} catch (UserRecoverableAuthException e) {
startActivityForResult(e.getIntent(), IntentConstants.REQUEST_GOOGLE_AUTHORIZATION);
} catch (IOException e) {
e.printStackTrace();
} catch (GoogleAuthException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String authToken) {
if (authToken != null) {
saveTokenAndGetCalendars(email, authToken);
}
}
};
String[] emails = new String[1];
emails[0] = email;
task.execute(emails);
}
一些附加说明
我正在点击 GoogleAuthException 并收到“未知”作为消息详细信息
我无法在此项目的 Google Cloud Console 权限中添加其他成员 - 添加新成员时,会出现一个弹出窗口,并显示“服务器错误。哎呀!我们的错误。”。我已经向 Google 发送了两次反馈。
我指的是这个文档。请注意下面的报价。通过“固定”,他们是说我不需要在我的 GOOGLE_CALENDAR_API_SCOPE 变量中添加观众:服务器:客户端ID?我已经尝试了有和没有,但仍然得到相同的 GoogleAuthException。
在这种情况下,Android 应用程序可以代表设备上的任何 Google 帐户调用 GoogleAuthUtil.getToken() 方法,范围参数值为 Audience:server:client_id:9414861317621.apps.googleusercontent.com。前缀 Audience:server:client_id: 是固定的,范围字符串的其余部分是 Web 组件的客户端 ID。
如果我使用这个范围,我可以从设备向谷歌进行身份验证。但是,我读过的文档表明我需要在范围内使用服务器 Web 客户端 ID(它与 android 客户端 ID 在同一个谷歌控制台项目中),以便服务器代表访问谷歌 api在 android 客户端上授权它的用户:
private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:https://www.googleapis.com/auth/calendar";
更新 1
我最初在回答中添加: 我的第一个问题的原因 - 我正在点击 GoogleAuthException 并收到“未知”作为消息详细信息 - 是我在云控制台中添加 android 客户端 ID 时犯的一个错误。SHA1 是正确的,但我没有正确输入包名称。当我的 android 包实际上是 com.company.android.app 时,我使用了 com.company.app。原始问题中的代码工作正常。只需确保您的 Google Cloud Console 项目中拥有所有必要的客户端即可。
但另一个问题仍然存在。当我将从GoogleAuthUtil.getToken()返回的一次性授权令牌发送到 Rails 后端,然后尝试将其交换为 access_token 和 refresh_token 时,我得到以下信息:
Signet::AuthorizationError:
Authorization failed. Server message:
{
"error" : "invalid_grant"
}
这个谷歌文档和几个 SO 帖子表明我需要设置access_type=offline
. 但我认为那是当您从 Web 服务器请求一次性授权代码和离线访问时。我正在尝试从 Android 客户端请求一次性授权代码并将其发送到 Web 服务器。
这可能与GoogleAuthUtil.getToken()吗?
更新 2
即使您只是尝试访问日历,Google Plus 登录也必须在范围内:
private final static String GOOGLE_CALENDAR_API_SCOPE = "oauth2:server:client_id:" + WEB_CLIENT_ID + ":api_scope:https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar";
这篇SO 帖子很有帮助。此外,谷歌的跨客户身份文件确实指出:
[注:此政策正在逐步推出。目前,当涉及访问令牌时,它仅适用于请求的范围包括https://www.googleapis.com/auth/plus.login。]
如果令牌交换适用于 Rails 后端,我将在答案中进行总结。