2012-04-20 20 views
5

Estoy intentando acceder a la API 3.0 de la lista de documentos de Google con OAuth 2.0, pero tengo algunos problemas con un error 401.OAuth - Token no válido: token de solicitud utilizado cuando no está permitido

Después usuarios han aceptado, mi código es el siguiente:

GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters(); 
oauthParameters.setOAuthConsumerKey(CLIENT_ID); 
oauthParameters.setOAuthConsumerSecret(CLIENT_SECRET); 
oauthParameters.setOAuthToken(token); 
oauthParameters.setOAuthTokenSecret(tokenSecret); 
oauthParameters.setScope("https://docs.google.com/feeds/"); 

service = new DocsService("myapp"); 
service.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer()); 

DocumentListFeed feed = service.getFeed(new URL("https://docs.google.com/feeds/default/private/full/?v=3"), DocumentListFeed.class); 

Luego, en la última línea -getFeed() - inicia la excepción:

com.google.gdata.util.AuthenticationException: Token invalid - Invalid token: Request token used when not allowed. 
<HTML> 
<HEAD> 
<TITLE>Token invalid - Invalid token: Request token used when not allowed.</TITLE> 
</HEAD> 
<BODY BGCOLOR="#FFFFFF" TEXT="#000000"> 
<H1>Token invalid - Invalid token: Request token used when not allowed.</H1> 
<H2>Error 401</H2> 
</BODY> 
</HTML> 

¿Qué está pasando? En una clase de prueba principal estática funciona como un amuleto, pero cuando la ejecuto en el servidor, esta línea ya no funciona. ¿Alguna idea?


RESUELTO

El token de acceso tiene que ser recuperada de esta manera, con un GoogleOAuthHelper, no con los GoogleOAuthParameters directamente:

String accessToken = oauthHelper.getAccessToken(oauthParameters); 
+0

Podría poner su solución en una respuesta y aceptar esa respuesta? De esta manera, la pregunta se marca como resuelta y si alguien entra en esta publicación (por cualquier motivo) será fácil encontrar la respuesta. –

+0

¿Qué es este oauthHelper? –

Respuesta

13

No está utilizando OAuth 2.0, pero OAuth 1.0 con HMAC-SHA1 como método de firma. Para usar OAuth 2.0, necesita al menos la versión 1.47.0 de la biblioteca gdata-java-client y la versión 1.8.0-beta de la biblioteca google-oauth-java-client.

El uso de la biblioteca google-api-java-client proporciona clases de ayuda para gestionar la implementación de OAuth 2.0 de Google.

Para recuperar credenciales de OAuth 2.0, puede utilizar este fragmento de código:

import com.google.api.client.auth.oauth2.Credential; 
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeRequestUrl; 
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest; 
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; 
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse; 
import com.google.api.client.http.HttpTransport; 
import com.google.api.client.http.javanet.NetHttpTransport; 
import com.google.api.client.json.jackson.JacksonFactory; 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.Arrays; 
import java.util.List; 

public class MyClass { 

    // Retrieve the CLIENT_ID and CLIENT_SECRET from an APIs Console project: 
    //  https://code.google.com/apis/console 
    static String CLIENT_ID = "<YOUR_CLIENT_ID>"; 
    static String CLIENT_SECRET = "<YOUR_CLIENT_SECRET>"; 
    // Change the REDIRECT_URI value to your registered redirect URI for web 
    // applications. 
    static String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob"; 
    // Add other requested scopes. 
    static List<String> SCOPES = Arrays.asList("https://docs.google.com/feeds"); 

    /** 
    * Retrieve OAuth 2.0 credentials. 
    * 
    * @return OAuth 2.0 Credential instance. 
    */ 
    static Credential getCredentials() throws IOException { 
    HttpTransport transport = new NetHttpTransport(); 
    JacksonFactory jsonFactory = new JacksonFactory(); 

    // Step 1: Authorize --> 
    String authorizationUrl = 
     new GoogleAuthorizationCodeRequestUrl(CLIENT_ID, REDIRECT_URI, SCOPES).build(); 

    // Point or redirect your user to the authorizationUrl. 
    System.out.println("Go to the following link in your browser:"); 
    System.out.println(authorizationUrl); 

    // Read the authorization code from the standard input stream. 
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 
    System.out.println("What is the authorization code?"); 
    String code = in.readLine(); 
    // End of Step 1 <-- 

    // Step 2: Exchange --> 
    GoogleTokenResponse response = 
     new GoogleAuthorizationCodeTokenRequest(transport, jsonFactory, CLIENT_ID, CLIENT_SECRET, 
      code, REDIRECT_URI).execute(); 
    // End of Step 2 <-- 

    // Build a new GoogleCredential instance and return it. 
    return new GoogleCredential.Builder().setClientSecrets(CLIENT_ID, CLIENT_SECRET) 
     .setJsonFactory(jsonFactory).setTransport(transport).build() 
     .setAccessToken(response.getAccessToken()).setRefreshToken(response.getRefreshToken()); 
    } 

    // … 
} 

Una vez que tenga la credencial de OAuth 2.0, puede autorizar a un objeto de servicio de la siguiente manera:

// ... 
import com.google.api.client.auth.oauth2.Credential; 
import com.google.gdata.client.docs.DocsService; 
import com.google.gdata.data.docs.DocumentListEntry; 
import com.google.gdata.data.docs.DocumentListFeed; 
import com.google.gdata.util.ServiceException; 
// ... 
import java.io.IOException; 
import java.net.URL; 
// ... 

public class MyClass { 
    // … 

    /** 
    * Print document entries using the provided authorized DocsService. 
    * 
    * @param credential OAuth 2.0 credential to use to authorize the requests. 
    * @throws IOException 
    * @throws ServiceException 
    */ 
    static void printDocuments(Credential credential) throws IOException, ServiceException { 
    // Instantiate and authorize a new DocsService object. 
    DocsService service = new DocsService("<YOUR_APPLICATION_NAME>"); 
    service.setOAuth2Credentials(credential); 

    // Send a request to the Documents List API to retrieve document entries. 
    URL feedUri = new URL("https://docs.google.com/feeds/default/private/full/"); 
    DocumentListFeed feed = service.getFeed(feedUri, DocumentListFeed.class); 

    for (DocumentListEntry entry : feed.getEntries()) { 
     System.out.println("Title: " + entry.getTitle().getPlainText()); 
    } 
    } 

    // ... 
} 

El CLIENT_ID , CLIENT_SECRET puede recuperarse del APIs Console y el REDIRECT_URI debe coincidir con uno que haya sido registrado con su Proyecto API.

+0

Gracias. Usted tenía razón. Corregido ya para ejecutar con OAuth2. Pero su código tiene un error, esta oración está al revés: .setRefreshToken (response.getAccessToken()). SetAccessToken (response.getRefreshToken()); – xuso

+0

Gracias, he arreglado la muestra :-) – Alain

+0

¿Puedes proporcionar el enlace para la dependencia de maven para este jar google-api-java-client? – Sanket

3

Así es como símbolo para añadir a OAuth2.0 Servicio GData:

SpreadsheetService service = new SpreadsheetService("MySpreadsheetIntegration-v1"); 

service.setOAuth2Credentials(new Credential(BearerToken 
    .authorizationHeaderAccessMethod()) 
    .setFromTokenResponse(new TokenResponse().setAccessToken(mToken))); 

asegúrese de importar todas las librerías necesarias (que es mucho).

El token de Android se debe obtener a través de Google Play Services mecanismo de OAuth:

String token = GoogleAuthUtil.getToken(String email, String scopes); 
+0

Esta respuesta complementa perfectamente la más votada ... @ zavidovych ¿ha considerado editar la otra respuesta para enriquecerla? –

Cuestiones relacionadas