Autenticación OAuth en Twitter con la librería Twitter4J (y II)

* Continuación del post https://mysticalpotato.wordpress.com/2010/10/25/autenticacion-oauth-en-twitter-con-la-libreria-twitter4j/

En el Post anterior se utiliza el método de autenticación para cuando la aplicación es una aplicación de escritorio, por lo que no hay acceso desde el navegador para inyectar datos en la aplicación (como el pin). Si optamos por especificar que la aplicación se ejecutará en un navegador (Aplicación Web usando J2EE, como Struts2 por ejemplo) podemos hacer que el usuario no tenga que ejecutar el paso de insertar el PIN manualmente. Simplemente logándose con su usuario y dando al botón “Permitir”, daría acceso a la aplicación.

La variación, además de en la configuración de la aplicación, está en el modo de recuperar el AccessToken que antes se ha cargado mediante el PIN. Ahora se utiliza una URL callback, mediante la cual Twitter envía a la aplicacion el código de autorización.

La URL de callback se especifica en la configuracion de la aplicación en dev.twitter.com, pero a día de escribir este post, no funciona correctamente, por lo que es mejor especificar en el código de Java la dirección.

public static String CALLBACKURL = "http://localhost:8084/TwitterPrueba1/callback.action";

Esta dirección se le pasa a Twitter para que responda, haciendo una petición con GET a la misma y añadiendo dos parámetros:

String oauth_token;
String oauth_verifier;

Un ejemplo de llamada puede ser:

http://127.0.0.1:8084/TwitterPrueba1/callback.action?oauth_token=2XN4aggw3f2QMoQXtnyck7MtBXIdBUGCNflzAMXXXX&oauth_verifier=MoQXtnyck7MtBXIdBUMoQXtnyck7MtBXIdBU</pre>

Estos parámetros se utilizarán, junto con el requestToken para generar el AuthToken, que como se vió en el post anterior, servirá para tener al usuario registrado en la aplicación y poder acceder a Twitter con sus credenciales.

AccessToken at = twitter.getOAuthAccessToken(requestToken, <strong>oauth_verifier</strong>);

En realidad oauth_token se le pasa a twitter a la hora de hacer la petición y éste lo devuelve en la llamada GET a la URL de callback, por lo que no es necesario. El parámetro que necesitamos es oauth_verifier.

¿Cómo se especifica la URL de callback que tiene que utilizar Twitter? Como he indicado antes hay dos métodos: en la configuración de la aplicación en dev.twitter.com o en el código de Java. Si se hace del primer modo, no está funcionando y en la llamada GET al callback no está metiendo el parámetro oauth_verifier… Así que el modo de solucionarlo es añadiendo la URL en el código directamente al crear el RequestToken:

Twitter twitter = new TwitterFactory().getInstance();
twitter.setOAuthConsumer(TwitterPruebas1.consumerKey, TwitterPruebas1.consumerSecret);

RequestToken requestToken = twitter.getOAuthRequestToken(<strong>CALLBACKURL</strong>);

Otro aspecto importante cuando se está probando la aplicación en local, es la diferenciación entre “localhost” y “127.0.0.1”. Estos dos términos son equivalentes si hablamos en términos de red, pero a la hora de las cookies de sesión son diferentes:

Si estamos usando para nuestras páginas “http://localhost:8084/TwitterPrueba1/&#8221;; y el callback es “http://127.0.0.1:8084/TwitterPrueba1/callback.action&#8221;; cuando la navegación pase por la autenticación de Twitter y éste redirija a la url 127.0.0… aparecerá una Sesión nueva para el navegador: son dos direcciones diferentes, y perderemos los objetos almacenados en la sesión de las url localhost. Esto me hizo perder un buen rato intentando avergiuar por qué se perdía la sesión en la llamada al callback.

El acceso a la autentiación de Twitter, que no deja de ser una URL proporcionada por la API, se deber hacer redirigiendo el flujo de navegación de forma automática. Para ello se puede establecer una variable con su getter y setter en la acción y utilizar las capacidades de redirección de Struts2:

this.setTwitterOAutURL(requestToken.getAuthorizationURL());

En la redirección de la acción:

${twitterOAutURL}

Esto redirige la navegación de forma automática cuando el resultado es “twitterURL4CallBack” a la URL que está en la variable twitterOAutURL (tiene que tener su getter).

La navegación queda en manos ahora de Twitter, por lo que tenemos que dividir el proceso en otra Acción nueva, que se encargará de recoger el código de Twitter para la generación del AccessToken.

¡Problema! Necesitamos pasar de una acción a otra los objetos de las clases RequestToken y Twitter. No es posible usar otros nuevos. Para ello siempre podemos usar el almacén de la sesión. En struts2, ambas acciones implementarán SessionAware.

this.sesion.put(LoginAction.REQUESTOKEN, requestToken);
this.sesion.put(LoginAction.TWITTER, twitter);    

La llamada de callback estará dirigida a una acción que se encarga de recuperar los parámetros que pasa Twitter por GET.

No es casualidad por tanto que en la acción de callback (callback.action), lo primero que se hace es recuperar las referencias a los objetos de las clases Twitter y RequestToken:

RequestToken requestToken = (RequestToken) this.session.get(LoginAction.REQUESTOKEN);
Twitter twitter = (Twitter) session.get(LoginAction.TWITTER); 

Finalmente, una vez se ha recibido la llamada de callback por parte de Twitter, se recogen los dos parámetros indicados (especialmente el oauth_verifier) para que, junto con el RequestToken, se cargue el AccesToken.

AccessToken at = twitter.getOAuthAccessToken(requestToken, oauth_verifier);

Una vez tenemos el AccessToken se puede proceder como se ha hecho en el primer post.

En resumen, hay que dividir el proceso en dos pasos: la creación del RequestToken, Twitter y solicitud de validación; y recogida del parámetro en la acción del callback, recuperando los objetos del primer paso y generando el AccessToken.

Anuncios

7 comments

  1. Saludos, pues estaba leyendo algo de lo que publicas, yo tengo algo parecido en un pequeño servlet, pero me gustaria saber si me puedes auxiliar, ¿Por que necesitamos el Oaut_verifier?
    y pues bueno, al igual que tu pierdo mi objeto twitter que anteriormente instancie, ¿que me suguieres hacer? no estoy usando struts ni spring.
    Se me ah ocurrido guardar en una coleccion el objeto twitter asi, si lo logro colectar, podria usarlo posteriormente.

    1. Hola,

      gracias por visitar el blog.

      El ouath_verifier es necesario para generar el objeto AccessToken, es el segundo parámetro. Sin él no funcionará. Nos lo proporciona Twitter en la llamada callback a nuestra aplicación. Sin ese parámetro no obtenedremos el AccessToken y por tanto no podrá instanciarse el cliente de twitter.

      Respecto al objeto Twitter, con los Servlets también tienes la posibilidad de acceder a los scopes de aplicación, a la sesión o al request. Dependiendo de tus necesidades puedes añadirlo a uno u otro.

      Si te refieres a usarlo un tiempo después, una vez reseteado el servidor sin hacer uso de los scopes, puedes guardar el token y el tokenSecret del AccesToken del usuario una vez logado. Con estos dos ćodigos puedes regenerar el AccesToken de nuevo y volver a instanciar el objeto twitter sin tener que realizar el proceso de login. Lo explico al final de este post: https://mysticalpotato.wordpress.com/2010/10/25/autenticacion-oauth-en-twitter-con-la-libreria-twitter4j/

      salu2

  2. Saludos de nuevo, haber, segun esto, entendi que si no introduzco lo que es el Oaut_verifier y el requestToken como parametros en el getOauthAccessToken no me podra dar mi accesToken, ni podre tampoco obtener el accessToken.getUserID ¿?
    podremos contactar por mail?, gracias

    1. Efectivamente, son los dos parámetros que necesitas para autenticar el usuario y una vez lo tienes autenticado podrás realizar las operaciones que quieras. Pero estos objetos los obtienes del proceso de autenticación.

      salu2

  3. Gracias hermano.
    Me sirvió mucho tu post. Pase horas y horas buscando la forma de persistir el Request Token hasta que lei que el callback hay que configurarlo como localhost, no como 127.0.0.1.

  4. Hola,
    Cuando te refieres a que son dos sesiones diferentes, a qué te refires exactamente?

    En mi primer servlet, en el que recojo el requestToken
    RequestToken requestToken = twitter.getOAuthRequestToken(“http://127.0.0.1:8080/DynamicProject/callback”);

    asi como el tokenSecret que almacenamos en sesión
    request.getSession().setAttribute(“requestTokenSecret”, requestToken.getTokenSecret());

    El problema que me aperece y que supongo que es al que te estas refierendo, es que en el segundo servlet, que esta mappeado con /callback, cuando twitter hace la redirección atendiendo a la Callback URL que definí al crear la appTwitter, http://127.0.0.1:8080/DynamicProject/callback” , entra en el servlet pero al recoger la session, los valores que se supone que almacené no están.

    ¿Qué se supone que está mal?

    Gracias de antemano!

    1. Hola,

      Me refiero a que la sesión se almacena en una cookie referida al dominio. El dominio 127.0.0.1 y localhost al final llevan al mismo lugar, pero a nivel de sesiones, son dos dominios diferentes y por tanto no podrás leer los atributos de la sesión. Por lo tanto si usas localhost, siempre usa ese término para el dominio y nunca 127.0.0.1; y viceversa.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s