Android 谷歌OAuth2-访问令牌&;刷新令牌->;无效的授权/代码已被兑换

Android 谷歌OAuth2-访问令牌&;刷新令牌->;无效的授权/代码已被兑换,android,google-app-engine,google-plus,google-calendar-api,google-oauth,Android,Google App Engine,Google Plus,Google Calendar Api,Google Oauth,我的目标是拥有某种长寿命的访问令牌,这样我的Android应用程序就可以读取用户当天谷歌日历上的事件,而无需每次都需要用户批准 我能够生成——我认为是——一次性授权代码;但是,当我将其发送到服务器端app engine时,我得到以下错误响应: 400正常 { “错误”:“无效的授权”, “错误描述”:“代码已被兑换。” } 这就是正在抛出的异常。我只是捕获它并将其发送回我自己,作为调试的一种方式 我得到的一次性代码以4/VUr开始,因此我假设它是一次性代码,而不是常规访问令牌 目前,在Andro

我的目标是拥有某种长寿命的访问令牌,这样我的Android应用程序就可以读取用户当天谷歌日历上的事件,而无需每次都需要用户批准

我能够生成——我认为是——一次性授权代码;但是,当我将其发送到服务器端app engine时,我得到以下错误响应:

400正常
{
“错误”:“无效的授权”,
“错误描述”:“代码已被兑换。”
}

这就是正在抛出的异常。我只是捕获它并将其发送回我自己,作为调试的一种方式

我得到的一次性代码以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();
}
这段代码来自,似乎这就是我必须做的

然后我将此代码发送到我的应用程序引擎端点。我使用来自的代码请求访问和刷新令牌

以下是我用作简单测试的代码:

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();
我的后端的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'
}
任何帮助都将不胜感激!谢谢

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


我只需要一种方法,在第一次使用后,无需用户交互就可以拥有某种长寿访问令牌。

我已经有一段时间没有参与这个项目了——它不再需要了

问题出在服务器端应用程序中。我只是请求的不正确。 一旦我的服务器端应用程序(应用程序引擎端点)从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;
    }
}

“代码已赎回。”当您尝试使用已使用的授权代码时,将引发错误。给定的授权代码只能使用一次。关于您的第二个问题,如果您不希望用户在授权您的应用程序后出现同意屏幕提示,请使用脱机访问。谢谢您的评论和链接,SGC。我正在尝试使用授权码进行脱机访问,以便获得刷新和访问令牌。也许我的问题是我没有正确地使我拥有的当前授权代码无效。看起来您提供的链接做了同样的事情,但使用的是REST,而不是我正在使用的API库。我尝试重置我的client_secret并获得了一个新的授权代码,但仍然得到相同的错误:/因此,这一定是我请求访问/刷新令牌的方式。您如何尝试使当前一次性代码无效?有任何答案吗对于这个问题,现在是什么时候?这是我的实际问题,但我试着从你的案例中得到想法。
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;
    }
}