我的目标是拥有某种长期存在的访问令牌,以便我的 Android 应用程序可以读取用户当天的 Google 日历事件,而无需每次都需要用户批准。
我能够生成——我认为是——一个一次性授权代码;但是,当我将其发送到我的服务器端应用程序引擎时,我收到以下错误响应:
400 OK
{
"error" : "invalid_grant",
"error_description" : "Code was already redeemed."
}
这就是抛出的异常。我只是捕获它并将其发送回给自己作为调试的一种方式。
我得到的一次性代码从4/VUr所以我假设它是一次性代码而不是常规访问令牌。
目前,在 Android 上,我允许用户使用 Google+ 登录,以便我获得他们的电子邮件地址。从那里我请求一个一次性授权码使用以下代码:
try {
Bundle appActivities = new Bundle();
appActivities.putString(GoogleAuthUtil.KEY_REQUEST_VISIBLE_ACTIVITIES, "http://schemas.google.com/AddActivity");
String scopes = "oauth2:server:client_id:" + Constants.SERVER_CLIENT_ID + ":api_scope:https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar";
//Plus.SCOPE_PLUS_LOGIN + " " + CalendarScopes.CALENDAR_READONLY;
String acctName = "myGmail";
String token = GoogleAuthUtil.getToken(getApplicationContext(), acctName, scopes, appActivities);
} catch (UserRecoverableAuthException e) {
startActivityForResult(e.getIntent(), 257/*REQUEST_AUTHORIZATION/*/);
} catch (Exception e) {
e.printStackTrace();
}
这段代码来自here https://developers.google.com/+/mobile/android/sign-in#enable_server-side_api_access_for_your_app看来这是我必须做的。
然后,我将此代码发送到我的 App Engine 端点。我使用的代码来自here https://developers.google.com/+/web/signin/server-side-flow#step_8_initialize_the_google_api_client_library_and_start_the_google_service请求访问和刷新令牌。
以下是我用作简单测试的代码:
HttpTransport transport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
//ArrayList<String> scopes = new ArrayList<>();
//scopes.add("https://www.googleapis.com/auth/plus.login");
//scopes.add("https://www.googleapis.com/auth/calendar");
GoogleTokenResponse tokenResponse = new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory,
SERVER_CLIENT_ID, SERVER_CLIENT_SECRET, code, "postmessage")/*.setScopes(scopes)*/.execute();
//urn:ietf:wg:oauth:2.0:oob
//postmessage
code = tokenResponse.getRefreshToken();
当我实例化时它就失败了GoogleAuthorizationCodeTokenRequest
举几个我见过的https://developers.google.com/accounts/docs/CrossClientAuth#offlineAccess https://developers.google.com/accounts/docs/CrossClientAuth#offlineAccess
Google-api-php 刷新令牌返回 invalid_grant https://stackoverflow.com/questions/14309726/google-api-php-refresh-token-returns-invalid-grant
从 Android 获取 Google oauth 授权令牌 - 返回 invalid_scope/ 未知错误 https://stackoverflow.com/questions/18361054/getting-google-oauth-authorization-token-from-android-return-with-invalid-scope
以不同方式设置重定向 uri 不起作用。
我确实填写了我的应用程序引擎项目的同意屏幕。已安装的 Android 客户端 id 和 Web 应用程序客户端 id 都在同一个项目中。我将我的应用程序的 Web 应用程序的重定向 uri 设置为 xxxxxxxx.appspot.com。
我的主应用程序的 Gradle:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// compile 'com.google.api-client:google-api-client:1.18.0-rc'
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'org.altbeacon:android-beacon-library:2.1.3'
compile 'com.google.apis:google-api-services-calendar:v3-rev118-1.19.1'
compile 'com.google.api-client:google-api-client-android:1.18.0-rc'
compile 'com.google.android.gms:play-services:6.5.87'
compile 'com.google.http-client:google-http-client-jackson:1.19.0'
compile project(path: ':beaconBackend', configuration: 'android-endpoints')
}
我的后端的 Gradle:
dependencies {
appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.14'
compile 'com.google.appengine:appengine-endpoints:1.9.14'
compile 'com.google.appengine:appengine-endpoints-deps:1.9.14'
compile 'javax.servlet:servlet-api:2.5'
}
任何帮助将不胜感激!谢谢!
另请注意,我已尝试使当前访问令牌(或一次性代码?)失效/撤销。
我只需要一种方法来获得某种长期有效的访问令牌,而无需在第一次后进行用户交互。