/user/info returning 401 status in response body

232 views
Skip to first unread message

Terry Jones

unread,
Mar 30, 2012, 8:38:51 PM3/30/12
to tumbl...@googlegroups.com
Hi all.

I have some code using the python-tumblpy library [1] to talk to the Tumblr
API.  It had been working fine for a month or two, but is now failing on
the /user/info call.  I took a look at the response from the API. The HTTP
status is 200, but the response body contains

{"meta":{"status":401,"msg":"Not Authorized"},"response":[]}

My failing code is very simple:

    api = Tumblpy(app_key='...', app_secret='...',
                  oauth_token='...', oauth_token_secret='...')
    userInfo = api.post('user/info')

I have verified that the values I'm passing to the constructor are correct.

Possibly related? When I visited http://tumblr.com a couple of hours ago
(i.e., using a web browser), it logged me out immediately and asked me to
agree to new TOS. Could it be that accounts cannot be accessed via the API
until sometime after the new terms are agreed to?

Are others seeing this behavior too?

Thanks!

Terry Jones

John Bunting

unread,
Mar 30, 2012, 8:46:45 PM3/30/12
to tumbl...@googlegroups.com
When did it start failing?
--
John Bunting

Simplicity is prerequisite for reliability
    --Edsger W. Dijkstra


John Bunting

unread,
Mar 30, 2012, 9:04:05 PM3/30/12
to tumbl...@googlegroups.com
I actually just did a test with the oauth2 library. This worked fine for me. https://gist.github.com/2258390

Want to try regening some keys and try? You can also email me off list to see if we can figure out if it's key specific.

Terry Jones

unread,
Mar 30, 2012, 9:21:10 PM3/30/12
to tumbl...@googlegroups.com
Hi John

Thanks for the quick reply - much appreciated. I've just been looking at the logs for the calls to access my Tumblr account. The last successful one was at 2012-03-29 15:11:47 UTC. Another call was made at 2012-03-29 10:16:42 UTC which hit the error. Subsequent calls all got the error.

Do you expire OAuth tokens?  There's no question of revocation BTW, as I'm looking at calls to my own Tumblr. The params being passed in the above two calls were the same. The version of python-tumblpy we're using (0.2.0) has been in place since 2012-02-27, so that's unchanged. I've tried it with a tiny script using the more recent 0.3.0 (which doesn't change anything that affects me AFAICT) and I get the same result.  I'm using an OAuth token & secret obtained a couple of hours ago.

I'll mail you off list seeing as this doesn't seem to be an issue affecting others.

Thanks again,
Terry

Terry Jones

unread,
Mar 30, 2012, 9:26:13 PM3/30/12
to tumbl...@googlegroups.com
I just tried the code in your gist with the keys that are failing for me with python-tumblpy and the call succeeds. Weird.... I have an apparently unchanged library, passing it unchanged keys, and what used to work now does not.  History would suggest PEBKAC!

Investigating....

Terry Jones

unread,
Mar 30, 2012, 9:49:39 PM3/30/12
to tumbl...@googlegroups.com
Hi again John. I'll keep posting here, in case someone else is using the Python lib.

Here's the issue.  The library makes the call using this code fragment.

https://gist.github.com/2258544

The req.to_url() call adds the oauth params to the URL, which AFAIK is an OAuth 1.0 thing and isn't needed in OAuth2.  If I simply pass the url to the self.client.request call (as in your gist), it succeeds. So it seems the python-tumblpy library shouldn't be adding the params etc.  Does the timing of my last successful call with this code correspond to a deploy on your side?

Thanks again. I have enough now to get this resolved.

Terry

felix bonkoski

unread,
Mar 31, 2012, 12:24:56 PM3/31/12
to tumbl...@googlegroups.com
1. Although the library is called "oauth2" it actually implements oauth 1.0.  There is no OAuth2 going on here at Tumblr.

2. You should be able to specify the oauth_blahblah  variables either in the HTTP Headers or in the URL.
   To me, this python-tumblpy library looks suspect.

   I don't think whoever wrote it knows what they are doing. I just briefly looked at the code on

   I saw this:
   self.headers.update({'Content-Type': 'application/json'})
   Uh, no? You woudn't set that on the HTTP request unless you are sending the server JSON.

   And also inside if method == 'POST': at line #209-215 his code is setting its own OAuth params?

   Again, wrong. The oauth2 library does that by itself with you call oauth2.Client.request

3. If I were you, I'd avoid this 'python-tumblpy' package. It seems to be wrong on many counts.
 
   Why it ever worked in the first place? Who knows. It probably shouldn't have.

felix

Terry Jones

unread,
Mar 31, 2012, 12:33:56 PM3/31/12
to tumbl...@googlegroups.com
Hi Felix

Thanks for the reply. I'd forgotten the heritage of oauth2 and that it's actually a cleanup of the original Python oauth module - thanks.

I ended up writing a bit of code myself, as I only use two API methods. See https://gist.github.com/2266563

Terry

Terry Jones

unread,
Mar 31, 2012, 12:40:48 PM3/31/12
to tumbl...@googlegroups.com
A couple more quick comments.
  • The code in my gist has some bits pulled out of Mike's library (thanks Mike).
  • Mike has obviously not been programming in Python for long, so it's to his credit he even tackled immediately making a library for others.
  • I guess the GET on the blog/.../posts URL doesn't need to be done via oauth, but that works so I left it that way as it's simple.
  • I noticed that GET works on /user/info, but followed the API docs to use POST. Do you use POST for some (security?) reason?
Terry

felix schwermut

unread,
Mar 31, 2012, 12:52:46 PM3/31/12
to tumbl...@googlegroups.com
Code looks fine.

1-2. Perhaps, but it doesn't help people to have a package that demonstrates a fundamental misunderstanding of the primary package it uses (oauth2).  Although granted, that code is convoluted as all hell. It took me a good 2 days to read and understand oauth2 and figure out how on earth to use it correctly.

3-4. yea i've noticed that on a few API methods. *shrug* Really there is no reason for /user/info to be an HTTP POST, as POST commands are generally only used when 1) server data would be mutated or the operation has side-effects or 2) you are sending the server a large chunk of information.  So, /user/info is a clear example of something that *should* be an HTTP GET, not POST :P
Reply all
Reply to author
Forward
0 new messages