Hi,

I'm having some fights with the Scribe java Library and using oauth to
post updates to Twitter form GAE. Setup:
- Scribe 0.6.6
- Scala 2.7.7
- running on Google App Engine (same behavior with local dev_appserver
of GAE)

I have 2 servlets:

The OAuthAuthorizationServlet does the initial steps to set up oAuth
and redirects to Twitter. It also puts requestToken en
requestTokenSecret on the session such that the can be used in the
callback.

      val session = req.getSession(true)
      session.setMaxInactiveInterval(-1)

      val scribe = Scribe.getInstance(props)
      val requestToken = scribe.getRequestToken()

      session.setAttribute("oauth-token", requestToken.getToken)
      session.setAttribute("oauth-tokenSecret",
requestToken.getSecret)

      resp.sendRedirect("http://api.twitter.com/oauth/authorize?
oauth_token=" + requestToken.getToken)

The above parts seems to work fine, redirects to Twitter, user
approves the authorization request and then Twitter redirects to my
OAuthCallbackServlet with the code below.
The problem now is that the second update request to Twitter always
fails with a 401 "Invalid / expired Token" on the call
"val accessToken3 = scribe.getAccessToken(new Token(token,
tokenSecret), oaverifier)"

I've also tried to used the token/tokenSecret/oaverifier in a separate
servlet to execute it, but that also results in an error. So I've got
the feeling that I'm doing something structurally wrong. When the user
has approved the oauth request on Twitter,
- What do you need to capture in the callback servlet so that you'll
be able to do following post (later in time) without having the user
to approve again?
- What calls do you have to make? I'm now only creating an
accessToken, but do I also have to create a requestToken?

      val scribe = Scribe.getInstance(props)
      val session = req.getSession(false)

      // token and tokenSecret are put on the session by the
OAuthAuthorizationServlet above
      val token = session.getAttribute("oauth-
token").asInstanceOf[String]
      val tokenSecret = session.getAttribute("oauth-
tokenSecret").asInstanceOf[String]
      val oaverifier = req.getParameter("oauth_verifier")

      // Post update test 1  <============= This first update works
fine
      val accessToken2 = scribe.getAccessToken(new Token(token,
tokenSecret), oaverifier)
      val request2 = new Request(Verb.POST, "http://twitter.com/
statuses/update.xml")
      request2.addBodyParameter("status", "test update" +
System.currentTimeMillis)
      scribe.signRequest(request2, accessToken2)
      logger.fine("Request headers: " + request2.getHeaders)
      logger.fine("Request body: " + request2.getBodyContents)

      val response2 = request2.send()
      logger.fine("Response headers: " + response2.getHeaders)
      logger.fine("Response body: " + response2.getBody)
      val statusCode2 = response2.getCode()
      resp.getOutputStream.println("<br/>Status code httpclient post :
" + statusCode2)
      val body2 = response2.getBody()
      resp.getOutputStream.println("<br/>body httpclient post : " +
body2)
      // EO Post update test 1

      // Try to do a second update using the same credentials
<=========== this update always fails, unless
      // I use the same access token as in the previous test
(accessToken2)

          // Next line results in the 401 error.
          val accessToken3 = scribe.getAccessToken(new Token(token,
tokenSecret), oaverifier)
          val request3 = new Request(Verb.POST, "http://twitter.com/
statuses/update.xml")
          request3.addBodyParameter("status", "test update" +
System.currentTimeMillis)

          // If I don't use accessToken3 here, but instead the earlier
created accessToken2 it does work.
          // But I also want to be able to post updates later, based
on the captured credentials, so that does not really help.
          scribe.signRequest(request3, accessToken3)

          val response3 = request3.send()
          logger.fine("Response headers: " + response2.getHeaders)
          logger.fine("Response body: " + response2.getBody)
          val statusCode3 = response3.getCode()
          resp.getOutputStream.println("<br/>Status code httpclient
post : " + statusCode3)
          val body3 = response3.getBody()
          resp.getOutputStream.println("<br/>body httpclient post : "
+ body3)


The scribe.properties file is as follows (XXXXXXX are dummy's of
course...):
consumer.key=XXXXXXXXX
consumer.secret=XXXXXXXXXX
request.token.verb=POST
request.token.url=https://api.twitter.com/oauth/request_token
access.token.verb=POST
access.token.url=https://api.twitter.com/oauth/access_token
#callback.url=http://kivanotify.appspot.com/oauth-callback
callback.url=http://localhost:8080/oauth-callback


Any help/clarification is appreciated.

Gero

Reply via email to