error 401 from oauth, starting a few days ago

102 views
Skip to first unread message

arlomedia

unread,
Jun 15, 2011, 1:09:16 PM6/15/11
to Twitter Development Talk
Last July I installed oauth-php to display items from my user timeline
on my website home page. I then copied the setup to another website
with another Twitter account and both have been working fine.

Then a few days ago both websites started returning error code 401,
"This method requires authentication." I can successfully run the
request_token command, but when I run the statuses/user_timeline
command I receive this error.

After experimenting with my own code for a while, I went back to
oauth's Twitter example code here:
http://code.google.com/p/oauth-php/source/browse/trunk/example/client/twoleggedtwitter.php.
This worked fine when accessing the public timeline, but when I
changed it to access the user timeline, I received the same
authentication error.

I've updated to the latest version of oauth, but that made no
difference. I also reset my consumer key and consumer secret key and
that made no difference, either.

Can someone tell me what might have changed in the last few days, or
how I should proceed with troubleshooting this?

Taylor Singletary

unread,
Jun 15, 2011, 1:53:09 PM6/15/11
to twitter-deve...@googlegroups.com
Hi Arlo,

Happy to help.

First, Twitter doesn't support any two-legged OAuth aside from the mandatory two-leggedness of the request token step of OAuth and the variant xAuth flow. Two-legged OAuth is where you sign requests and present your API key but you have no "user context" (the access/oauth_token). If you're signing an API request with OAuth, you must include an oauth_token to provide context on the user who is making the request.

We're more strictly enforcing correctness in OAuth signatures and requests now. Is the account that you're trying to retrieve the user_timeline for a protected account? Are you using API urls in the style of http://api.twitter.com/1/statuses/home_timeline.json ?

If you want to access a resource without a user context, you should simply directly request the resource without attaching any kind of authorization to the request at all.

Thanks,
@episod - Taylor Singletary



--
Twitter developer documentation and resources: https://dev.twitter.com/doc
API updates via Twitter: https://twitter.com/twitterapi
Issues/Enhancements Tracker: https://code.google.com/p/twitter-api/issues/list
Change your membership to this group: https://groups.google.com/forum/#!forum/twitter-development-talk

arlomedia

unread,
Jun 16, 2011, 12:40:20 PM6/16/11
to Twitter Development Talk
Thanks for the reply. On one website, I'm accessing the timeline for a
protected account; on the other website, the account is not protected.
For both, I'm using this URL: https://api.twitter.com/statuses/user_timeline.xml.
Both stopped working last week.

The oauth example script I posted above requests the oauth token and
secret from the account, then passes it back with the request (you can
see that by checking the $params value before the request). In my own
script, I simply have the token and secret saved in constants and then
I pass them from there. Neither approach is working for me now. I did
notice that the token and secret returned by the request_token API
call are different from the token and secret that I see displayed on
the my_token page in my Twitter account (https://dev.twitter.com/apps/
nnnnnn/my_token), and the values returned from the API are different
every time. Does that tell us anything?

Here's what my request_token request looks like:

POST https://api.twitter.com/oauth/request_token
Authorization: OAuth realm="", oauth_signature_method="HMAC-SHA1",
oauth_signature="[27 characters]%3D", oauth_nonce="[13 characters]",
oauth_timestamp="1308241110", oauth_token="",
oauth_consumer_key="[consumer key]", oauth_version="1.0"
Content-Type: application/x-www-form-urlencoded

This returns values for oauth_token, oauth_token_secret and
oauth_callback_confirmed (but the token values don't match what I see
in my account).

Here's what my user_timeline request looks like:

GET https://api.twitter.com/statuses/user_timeline.xml
Authorization: OAuth realm="", oauth_token="[oauth token]",
oauth_token_secret="[oauth token secret]",
oauth_signature_method="HMAC-SHA1", oauth_signature="[27 characters]
%3D", oauth_nonce="[13 characters]", oauth_timestamp="1308241629",
oauth_consumer_key="[consumer key]", oauth_version="1.0"

This returns the 401 error whether I send the token values returned by
request_token or the token values I got from my account.

Taylor Singletary

unread,
Jun 16, 2011, 12:56:39 PM6/16/11
to twitter-deve...@googlegroups.com
Hi Arlo,

A few minor points here:
  - What type of perms do you have set for your API key: RO, RW, or RW+DM? 
  - The "my access token" feature can only yield RO and RW tokens. If you've set your app to RW+DM, you'll get a different kind of token when walking through the OAuth web-flow than you get for the my access token flow (which may explain why you'll see the differing values)

Most importantly:
  - You aren't accessing valid API URLs. https://api.twitter.com/statuses/user_timeline.xml should have a version: https://api.twitter.com/1/statuses/user_timeline.xml
  - Your authorization header contains your oauth_token_secret -- which should be kept secret and not included in your request. oauth_token_secret is only used as part of the signing process, it's not a value that you'll ever need to send to the API.

@episod - Taylor Singletary



--

arlomedia

unread,
Jun 16, 2011, 1:35:08 PM6/16/11
to Twitter Development Talk
Hello,

I wondered about the version number in the URL; but when I add that, I
get the same error. I also removed the token secret from the request
parameters.

Where would I set the permissions on the API key? I'm not familiar
with that process. In any case, my own scripts were just passing the
keys I had copied and pasted from my Twitter account, so that approach
should still work, right?

In my requests (which are generated by the oauth-php library) I
noticed that the signature line is a single value followed by an
encoded ampersand. Is that correct, for the specified authentication
method?

Thanks,
-Arlo

arlomedia

unread,
Jun 17, 2011, 11:07:04 AM6/17/11
to Twitter Development Talk
Just giving this a bump for Taylor.

For anyone else, does the oauth-php example script work with your
accounts? It works for me when accessing the public timeline as shown
in the example, but if I change the request URL to access my user
timeline (protected or unprotected) I get the authorization error.

It would be helpful to know if the problem is with my account, the
example script, or the oauth-php library.

Matt Harris

unread,
Jun 23, 2011, 3:16:58 PM6/23/11
to twitter-deve...@googlegroups.com
Hi Arlo,

When an error is returned by the API we include some information about the cause in the response body. Take a look at that response body and see if that helps you resolve the problem.

If not, let us know what the error says and what your OAuth basestring and authorization header/parameters are. Remember to remove your oauth and consumer secrets though.

Best,
@themattharris
Developer Advocate, Twitter




arlomedia

unread,
Jun 24, 2011, 12:25:02 PM6/24/11
to Twitter Development Talk
The response body only includes the text of the error message ("This
method requires authentication") and a copy of my request URI.

I included my complete request including all headers in an earlier
post in this thread; is that what you meant by "authorization header/
parameters"?

Matt Harris

unread,
Jun 24, 2011, 7:32:54 PM6/24/11
to twitter-deve...@googlegroups.com
Thanks. I was asking about the code as Taylor made a few suggestions about issues with your code. I was wondering if you had implemented them yet.

In particular have you updated your URLs to use the correct domain with the /1 included. For example: 
and have you removed the oauth_token_secret from your authorisation header?

Best,
@themattharris
Developer Advocate, Twitter




arlomedia

unread,
Jun 27, 2011, 1:21:05 PM6/27/11
to Twitter Development Talk
Yes, I've made both of those changes, as I mentioned in my June 16
post. I just ran the requests again; here's what the request headers
look like now. The first is the token request and the second is the
timeline request:

POST https://api.twitter.com/oauth/request_token
Authorization: OAuth realm="", oauth_signature_method="HMAC-SHA1",
oauth_signature="[8 chars]%2F[18 chars]%3D", oauth_nonce="[13 chars]",
oauth_timestamp="1309193079", oauth_token="",
oauth_consumer_key="[consumer key from application settings page]",
oauth_version="1.0"
Content-Type: application/x-www-form-urlencoded

(This returns a response body containing name/value pairs for
oauth_token, oauth_token_secret and oauth_callback_confirmed. However,
the token values don't match the token values I see when I log into my
Twitter account and look at my application settings.)

GET https://api.twitter.com/1/statuses/user_timeline.xml?count=1
Authorization: OAuth realm="", oauth_token="[access token from
application settings page]", oauth_signature_method="HMAC-SHA1",
oauth_signature="%2F[26 chars]%3D", oauth_nonce="[13 chars]",
oauth_timestamp="1309193079", oauth_consumer_key="[consumer key from
application settings page]", oauth_version="1.0"

(This returns a response body containing the same error as before,
"This method requires authentication." The response also includes the
HTTP header "X-Warning: Invalid OAuth credentials detected.")

Does the URL for the first request also need to contain the version
number? Taylor didn't mention that, but when I add it, that first
request returns the error "Request failed with code 401: Invalid /
expired Token." I'm not sure if I even need that first request,
because I can get the access token manually from my application
settings page.

arlomedia

unread,
Jul 1, 2011, 9:55:55 AM7/1/11
to Twitter Development Talk
FYI, one of my clients decided to pull this from the site rather than
spend any more money troubleshooting it. I've hidden it from the other
site but may come back later and try a different OAuth library if I
have time. I can't use the pre-built widgets because they don't offer
enough flexibility in sizing and appearance.

Basic authentication was pretty easy to set up and worked fine; OAuth
was a bigger effort to set up but worked fine until it broke. I don't
understand why something as simple as showing my last five Twitter
posts should be so complicated as to require a third-party library
with dozens of scripts and repeated API changes that are not backwards
compatible. I'm submitting this as feedback on your new system -- you
just lost a featured position on two websites because of its
complexity and instability.
Reply all
Reply to author
Forward
0 new messages