Google OAuth2 - 访问令牌和刷新令牌 -> invalid_grant/代码已兑换

2024-04-22

我的目标是拥有某种长期存在的访问令牌,以便我的 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'
}

任何帮助将不胜感激!谢谢!

另请注意,我已尝试使当前访问令牌(或一次性代码?)失效/撤销。

我只需要一种方法来获得某种长期有效的访问令牌,而无需在第一次后进行用户交互。


我从事这个项目已经有一段时间了——不再需要它了。

问题出在服务器端应用程序内。我只是没有正确要求它。 当我的服务器端应用程序(App Engine Endpoint)收到来自 Android 应用程序的刷新令牌后,我在服务器端执行了以下操作。

private String refreshAccessToken(String refreshToken, String clientId, String clientSecret) throws IOException {
    try {
        TokenResponse response =
                new GoogleRefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(),
                        refreshToken, clientId, clientSecret).execute();
        return response.getAccessToken();
    } catch (TokenResponseException e) {
        return null;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google OAuth2 - 访问令牌和刷新令牌 -> invalid_grant/代码已兑换 的相关文章

随机推荐