Revoke an access token programmatically - always getting a 403/Forbidden


#1

Hello,

I’m totally struggling trying to revoke an access token using the API, as described here: https://dev.twitter.com/docs/auth/application-only-auth

I have code in VB.NET that executes the query and is always returned a 403/Forbidden with the following error: {“errors”:[{“code”:99,“label”:“authenticity_token_error”,“message”:“Unable to verify your credentials”}]}

I also tried a manual request in Fiddler and I am getting the same result. Which means there must be something I don’t understand in how this is supposed to be done.

So I have the following:

  • a consumer key (the unique application key)
  • a consumer secret (the unique application secret)
  • a user’s access token (a user that got an access token from the above application)
  • a user’s access token secret (which doesn’t seem to be used anywhere in the process)

The authorization header I add to the request is a base64 encoding of the concatenation of the consumer key and consumer secret with a colon in-between, as described by the documentation.
The body of the request is access_token=xxxx where xxxx is the user access token.

I always get the same 403 error. The documentation says this errors occurs when trying to:

  • Obtain or revoke a bearer token with incorrect or expired app credentials --> I know the app credentials (consumer key + consumer secret, right?) is correct and not expired, because I can query the API successfully with the same credentials
  • Invalidate an incorrect or revoked bearer token --> I know the bearer token (user access token, right?) is correct, because I can query the API successfully with it.

What am I doing wrong?

Thanks!

For the record, the VB code is the following:

        Dim tRequest As HttpWebRequest = HttpWebRequest.Create("https://api.twitter.com/oauth2/invalidate_token")
        tRequest.Method = "POST"
        tRequest.ContentType = "application/x-www-form-urlencoded"
        tRequest.Headers.Add("Authorization", "Basic " & Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(Tools.Configuration.TwitterClientID & ":" & Tools.Configuration.TwitterClientSecret)))

        Dim tBody As String = "access_token=" & tUser.TwitterAccessToken
        Using tStreamWriter As New StreamWriter(tRequest.GetRequestStream)
            tStreamWriter.Write(tBody)
            tStreamWriter.Flush()
        End Using

        Dim tResponse = tRequest.GetResponse()

#2

I am having the same issue, and I happen to post a question about it a couple of hours after this.
(https://dev.twitter.com/discussions/19566)

Just like you wrote, I am pretty sure about the authorization header, because I obtain the access_token with the same authorization header with the oauth2/token method.
And I know that the access_token works, because I can get user_timeline response with the bearer token.
but invalidate_token returns 403.

this leads me to think that the problem could be caused by improper encoding of the access_token in the post method. I tried several things, like percent encoding, and reverse percent encoding. I still get the 403.

Have you found a solution for this?


#3

up, same issue.


#4

I am having the same issue as well. Please share if you happen to find a solution eventually.


#5

No solution yet - will post here if I happen to find one. You’re welcome to post a solution as well if you find one :wink:


#6

I’ve tried to reproduce this using typical circumstances but cannot reproduce.

Do you know more about how the result of your programming/configuration expresses itself by the time it’s an actual HTTP request?

While it’s not likely related, it does look like you’re setting a content body, setting the content-type – but are you also sending a Content-Length header along with the POST?

I’m not familiar with your library – I also assume that “tUser.TwitterAccessToken” represents the application-only auth “bearer token” rather than a user-based OAuth 1.0A access token?


#7

II was able to get a positive answer with the following set of headers. However, after a couple of tests, I started getting errors again. So I changed to another consumer secret and key, and it worked again. I must have hit the rate limit error I think.

conn.setRequestProperty("Host", HOST); conn.setRequestProperty("User-Agent", USER_AGENT); conn.setRequestProperty("Authorization", authHeader); conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";" + CHARSET); conn.setRequestProperty("Content-Length", "" + stringifiedParams.getBytes("UTF-8").length); conn.setRequestProperty("Accept-Encoding", "gzip");

host is api.twitter.com
user_agent is whatever…
authHeader is exactly the same as you use in /oauth2/token endpoint.
content type and charset application/x-www-form-urlencoded;charset=UTF-8
stringifiedParams is basically percent-encoded accesss token and key.
(access_token=AAAAA…) percent encoded access token is the same value as returned from /oauth2/token endpoint.
you should also write this data into the output stream.

I hope this helps…


#8

Hello Taylor,

The Content-Length is set automatically by HttpWebRequest. I have checked the outgoing request with fiddler to make sure of it.

I am lost with all those tokens and oAuth things. So precisely I am using the following procedure to get the user tokens: http://www.rssbus.com/kb/help/RTR2-A/pg_etoauthaccesstoken.rst (because our application uses this library). This gives me, for a user, an “oAuth Access Token” and an “oAuth Access Token Secret”. Those are stored and used per the library for later uses.

Now in my previous code, “tUser.TwitterAccessToken” is that “oAuth Access Token”. Is this correct? I am confused between the “bearer token” and the “oAuth 1 access token”. Could it be that the library I am using does not get the right kind of token?

edit: so if the component actually uses oAuth 1.0a, I have no way of revoking the token, right?


#9

Ok so I was indeed confused with oAuth 1.0a and oAuth 2. I was trying to revoke a oAuth 1.0a token, which I understand is not possible to do.

Thank you!


#10

invalidate_token was giving me grief until I realized /oauth2/token returns a token that is already URL encoded. Passing that to an HTTP library that accepts form field values and generates the body, for you, results in double encoding. Either set the raw body yourself, or URL decode the token before passing it to your HTTP library.