Search code examples
c#apitwittertwitter-oauthspring-social-twitter

Invalid / expired Token - 401 - Unauthorized (Authorization Required) using Spring.Social.Twitter


I am using the Spring.Net Framework (spring.rest, spring.social.core and spring.social.twitter (2.x - oauth 1.0a) with c#.

The idea of the application will be for an event, people can link their twitter account to the event and as results are received for that person. The persons result it posted to their twitter account.

It will be made up of a website where users will register and give access. Then a console application which will process results (using the saved token set to post to registered users.

I have a web mvc application that asks a user to sign in and authorise an application so that it can post on behalf of the user. This information returned (token etc) is encrypted and kept in a db linked to the user. e.g. Our website - redirect to callback url - twitter - sign in +permission - back to callback url - store token info in db encrypted.

I then have a console application (eventually a service) which looks at results, when we have a result for a person with twitter account associated and permission given. We use that information to post to their account (their result).

The sign up process works fine, and i can post to the signed up person. saying they've registered. (website)

The console application initially worked to be able to post up results.

However, suddenly I am getting ( i think this is just a time frame (approx an hour) - works soon as a they register.)

"POST request for 'https://api.twitter.com/oauth/access_token' resulted in 401 - Unauthorized (Authorization Required)."

Linked to a user (in our system) - i am encrypting and storing verifier (from callback), secret and value. I then am using this to exchange for a access token to get secret and value to be able to post.

This is currently all a demo (going to 127.0.0.1) for a proof of concept. So far only tried all this with the Spring.Social framework (c#)

When it works via console application -- RAW -

REQUEST
POST https://api.twitter.com/oauth/access_token HTTP/1.1
Accept: application/x-www-form-urlencoded,multipart/form-data,/
Authorization: OAuth oauth_consumer_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
, oauth_signature_method="HMAC-SHA1"
, oauth_timestamp="1417007918"
, oauth_nonce="1784014115"
, oauth_version="1.0"
, oauth_token="yyyyyyyyyyyyyyyyyyyyyyyyyyy"
, oauth_verifier="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
, oauth_signature="vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
Content-Type: application/x-www-form-urlencoded
Host: api.twitter.com
Content-Length: 0
Connection: Keep-Alive

RESPONSE
HTTP/1.1 200 OK
cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
content-length: 167
content-security-policy: default-src https:; connect-src https:; font-src https: data:; frame-src https:; img-src https: data:; media-src https:; object-src https:; script-src 'unsafe-inline' 'unsafe-eval' https:; style-src 'unsafe-inline' https:; report-uri https://twitter.com/i/csp_report?a=NVXW433SMFUWY%3D%3D%3D&ro=false;
content-type: text/html; charset=utf-8
date: Wed, 26 Nov 2014 13:18:40 UTC
etag: "fbf12c0103c8a9a4e85476ebc4a721fb"
expires: Tue, 31 Mar 1981 05:00:00 GMT
last-modified: Wed, 26 Nov 2014 13:18:39 GMT
pragma: no-cache
server: tsa_b
set-cookie: twittersess=BAh7BzoPY3JlYXRlZF9hdGwrCAnzQOxJAToHaWQiJTZjODM4ZWMwZDg4ZjY0%250ANGFjYWE0N2M1YWU0MmMzNmZl--af2ffe955256e30da84bc52b585d7c30b6926284; domain=.twitter.com; path=/; secure; HttpOnly
set-cookie: guest_id=v1%3A141700791973784560; Domain=.twitter.com; Path=/; Expires=Fri, 25-Nov-2016 13:18:40 UTC
status: 200 OK
strict-transport-security: max-age=631138519
vary: Accept-Encoding
x-connection-hash: bd73d7f87abb9c16caef67f675d8641b
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-mid: 4e5118e4376219e001674f1292c123965885210f
x-runtime: 0.10480
x-transaction: d24c3b12ea39be37
x-ua-compatible: IE=edge,chrome=1
x-xss-protection: 1; mode=block

oauth_token=xxxxx-xxxxxxxxxxxxxxxxxxxxxx&oauth_token_secret=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy&user_id=2xxxxxxxxxxxxxx&screen_name=naxxxxxx

After about an hour(couple of hours in this instance) same code will fail.... with HTTP/1.1 401 Authorization Required - Invalid / expired Token.

REQUEST
POST https://api.twitter.com/oauth/access_token HTTP/1.1
Accept: application/x-www-form-urlencoded,multipart/form-data,*/*
Authorization: OAuth oauth_consumer_key="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
, oauth_signature_method="HMAC-SHA1"
, oauth_timestamp="1417018992"
, oauth_nonce="2294192392"
, oauth_version="1.0"
, oauth_token="yyyyyyyyyyyyyyyyyyyyyyyyyyy"
, oauth_verifier="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
, oauth_signature="vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
Content-Type: application/x-www-form-urlencoded
Host: api.twitter.com
Content-Length: 0
Connection: Keep-Alive

RESPONSE
HTTP/1.1 401 Authorization Required
cache-control: no-cache, no-store, must-revalidate, pre-check=0, post-check=0
content-length: 136
content-security-policy: default-src https:; connect-src https:; font-src https: data:; frame-src https:; img-src https: data:; media-src https:; object-src https:; script-src 'unsafe-inline' 'unsafe-eval' https:; style-src 'unsafe-inline' https:; report-uri https://twitter.com/i/csp_report?a=NVXW433SMFUWY%3D%3D%3D&ro=false;
content-type: text/html; charset=utf-8
date: Wed, 26 Nov 2014 16:23:13 UTC
expires: Tue, 31 Mar 1981 05:00:00 GMT
last-modified: Wed, 26 Nov 2014 16:23:13 GMT
pragma: no-cache
server: tsa_b
set-cookie: _twitter_sess=BAh7CDoPY3JlYXRlZF9hdGwrCEzs6exJAToHaWQiJWI5MDgzMzk0Y2FhMGY2%250AMGNlNmEyYzQzZjk5OGEyNjAyIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVy%250AOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--86562a75e3ddabab3c688e726e6c42fe37a067ea; domain=.twitter.com; path=/; secure; HttpOnly
set-cookie: guest_id=v1%3A141701899357688419; Domain=.twitter.com; Path=/; Expires=Fri, 25-Nov-2016 16:23:13 UTC
status: 401 Unauthorized
strict-transport-security: max-age=631138519
vary: Accept-Encoding
www-authenticate: OAuth realm="https://api.twitter.com"
x-connection-hash: 24d849ec3bead25133b581794d34c74f
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-mid: aed281dc4b2e3fb483737ccd772ce1d8d3f6064d
x-transaction: d41ff14981c7a0ec
x-ua-compatible: IE=edge,chrome=1
x-xss-protection: 1; mode=block

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <error>Invalid / expired Token</error>
  <request>/oauth/access_token</request>
</hash>

Can anyone help or advice on what I should be persisting to be able to post on behalf of a user - once they've given us permission from a service or console application.

Thanks in advance.


Solution

  • I managed to solve issue. I removed Spring.Social from equation and wrote some quick code to talk to Twitter API without a framework, this gave me a better understanding of what the steps and process were.

    Using this I then re-added the framework and I think I use it correctly now. As it all works.

    My issue was that once I got my request token+verifier - supplying callback, consumer etc. I then used that to get an access token to perform posts etc.

    However, every time I attempted to post I tried to exchange request token value + secret and verifier to get the access token. This eventually fails.

    I changed code to save returned access token and just use that directly, works fine now.