6

Moim celem jest posiadanie życiowego tokena dostępu, aby moja aplikacja na Androida mogła czytać wydarzenia z kalendarza Google danego użytkownika bez konieczności zatwierdzenie użytkownika za każdym razem.Google OAuth2 - token dostępu i token odświeżania -> invalid_grant/Code został już wykorzystany

Jestem w stanie wygenerować - jak sądzę - jednorazowy kod autoryzacyjny; Jednak, kiedy wysłać to mojej stronie serwera, App Engine, otrzymuję następujące odpowiedzi błędzie:

400 OK { "error" : "invalid_grant", "error_description" : "Code was already redeemed." }

To jest wyjątek, który jest wyrzucane. Po prostu łapię to i wysyłam do siebie jako sposób na debugowanie.

Jednorazowy kod, który otrzymuję zaczyna się od 4/VUr, więc zakładam, że jest to jednorazowy kod, a nie zwykły token dostępu.

Obecnie na Androida zezwalam użytkownikowi na logowanie się przy użyciu Google+, dzięki czemu mam ich adres e-mail. Stamtąd zażądać jednorazowy kod autoryzacyjny z następującego kodu:

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

Ten kod jest od here i wydaje się, że to, co muszę zrobić.

Następnie wysyłam ten kod do mojego punktu końcowego aplikacji do urządzenia. Używam kodu od here, aby poprosić o dostęp i odświeżenie tokena.

Poniżej znajduje się kod, który używam jako prostego testu:

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

się niepowodzeniem prawo kiedy instancję GoogleAuthorizationCodeTokenRequest

Pośród Widziałem https://developers.google.com/accounts/docs/CrossClientAuth#offlineAccess
Google-api-php Refresh Token returns invalid_grant
getting Google oauth authorization token from Android- return with invalid_scope/ Unknown error

Ustawianie przekierowania uri inaczej nie działał. Wypełniłem ekran zgody na projekt mojego silnika aplikacji. Zarówno zainstalowany identyfikator klienta Android, jak i identyfikator klienta aplikacji sieciowej są w tym samym projekcie. Mam przekierowanie uri dla aplikacji internetowej ustawionej na xxxxxxxx.appspot.com dla mojej aplikacji.

Gradle dla mojego głównego aplikacji:

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 dla mojego backend:

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' 
} 

Każda pomoc będzie bardzo mile widziana! Dzięki!

Należy także pamiętać, że próbowałem unieważnić/unieważnić obecny token dostępu (lub jednorazowy kod?).

Po prostu potrzebuję sposobu na posiadanie pewnego rodzaju długiego żetonu dostępu bez interakcji z użytkownikiem po raz pierwszy.

+0

"Kod został już wykorzystany." błąd jest zgłaszany, gdy próbujesz użyć kodu autoryzacji, który był już używany. Podany kod autoryzacji można wykorzystać tylko raz. Jeśli chodzi o Twoje drugie pytania, jeśli nie chcesz, aby użytkownik był monitowany o ekran zgody po autoryzowaniu aplikacji, przejdź do trybu offline https://developers.google.com/accounts/docs/OAuth2WebServer#offline – SGC

+0

Dziękuję za komentarz i link, SGC. Próbuję uzyskać dostęp w trybie offline przy użyciu kodu autoryzacji, aby uzyskać odświeżenie i token dostępu. Być może moim problemem jest to, że nie poprawiam poprawnie obecnego kodu autoryzacji, który mam. Wygląda na to, że podany przez ciebie link działa tak samo, ale używa REST zamiast bibliotek API, z których korzystam. – Markymark

+0

Próbowałem zresetować moje client_secret i otrzymałem nowy kod autoryzacji, ale nadal mam ten sam błąd:/więc musi to być sposób w jaki żądam dostępu/odświeżenie tokena – Markymark

Odpowiedz

2

Minęło trochę czasu, odkąd pracowałem nad tym projektem - nie było już potrzebne.

Problem był w aplikacji po stronie serwera.Po prostu nie prosiłem o to poprawnie. Gdy moja aplikacja po stronie serwera (App Engine Endpoint) otrzymała odświeżający token z aplikacji na Androida, zrobiłem to po stronie serwera.

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; 
    } 
} 
+0

http://stackoverflow.com/questions/33754177/google-analytics-custom-plugin-getting-error-invalid-grant To jest mój rzeczywisty problem, ale próbuję zdobyć pomysł z twojej strony. –