Http 403 - Forbidden and code 99 (authenticity_token_error)

android
oauth
java
api

#1

I want to implement application only authentication for twitter in Java, just the way it is descried in this documentation: https://dev.twitter.com/oauth/application-only .

My Java code to obtain the bearer token looks like this:

String consumerKey = URLEncoder.encode(RandomStringUtils.randomAlphabetic(15));
String consumerSecret = URLEncoder.encode(RandomStringUtils.randomAlphabetic(25));
String credentials = consumerKey + ":" + consumerSecret;
String credentialsEncoded = Base64.encodeToString(credentials.getBytes("UTF-8"), Base64.NO_WRAP);
Log.d(DEBUG_TAG, "credentials = " + credentials);
Log.d(DEBUG_TAG, "credentialsEncoded = " + credentialsEncoded);

URL url = new URL("https://api.twitter.com/oauth2/token");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
conn.setConnectTimeout(15000);
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("User-Agent", "My Twitter App v1.0.23");
conn.setRequestProperty("Host", "api.twitter.com");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
conn.setRequestProperty("Authorization", "Basic " + credentialsEncoded);
conn.setRequestProperty("Accept-Encoding", "gzip");
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write("grant_type=client_credentials");
writer.flush();
writer.close();
os.close();
int responseCode = conn.getResponseCode();
Log.d(DEBUG_TAG, "responseCode = " + responseCode);
Log.d(DEBUG_TAG, "conn.getResponseMessage() = " + conn.getResponseMessage());
String line = null;
String response = "";
BufferedReader br = null;
try {
        br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} catch (Exception ex) {
        br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
} finally {
        while ((line = br.readLine()) != null) {
            //Log.d(DEBUG_TAG, "line = " + URLDecoder.decode(line,"UTF-8"));
            response += line;
        }
}
Log.d(DEBUG_TAG, "response = " + URLDecoder.decode(response, "UTF-8"));

Unfortunatley the output is always like this:

responseCode = 403
conn.getResponseMessage() = Forbidden
response = ����������������Q�0�޷�{�Y�SC�,l�B�^�����Z��<u&����a��^�G�)3��/---4�-D���IrE�,�����mc�6��Y��������������$�{i������

Is something wrong with my implementation? Did I understand the documentation in a wrong way?


#2

OAuth can be tricky - I’d recommend looking at Twitter4J’s implementation, or (since you’ve tagged this as “android”), looking at Twitter Kit, which we provide as a native SDK for Android with source code available on Github.


#3

Thanks for your tip. I will look into that.

But can you tell me exactly whats wrong with my Code?

I found many posts describing the same problem, but none of the solutions did work for me.


#4

Ok I implemented something with the Android Twitter Kit:

TwitterConfig config = new TwitterConfig.Builder(this)
                .logger(new DefaultLogger(Log.DEBUG))
                .twitterAuthConfig(new TwitterAuthConfig(
                        getResources().getString(
                                R.string.CONSUMER_KEY),
                        getResources().getString(
                                R.string.CONSUMER_SECRET)))
                .debug(true)
                .build();
Twitter.initialize(config);
TwitterApiClient twitterApiClient = TwitterCore.getInstance().getApiClient();
StatusesService statusesService = twitterApiClient.getStatusesService();
Call<List<Tweet>> timelineCall = statusesService.userTimeline(null, "twitterapi", null, null, null, null, null, null, null);
timelineCall.enqueue(new Callback<List<Tweet>>() {
            @Override
            public void success(Result<List<Tweet>> result) {
                System.out.println("success, result = " + result);
            }

            @Override
            public void failure(TwitterException exception) {
                System.out.println("failure, exception = " + exception);
            }
});

But i still get a 403 respectively 400 error:

**E/Twitter: Failed to get app auth token**
**           com.twitter.sdk.android.core.TwitterApiException: HTTP request failed, Status: 403**
**               at com.twitter.sdk.android.core.Callback.onResponse(Callback.java:42)**
**               at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)**
**               at android.os.Handler.handleCallback(Handler.java:751)**
**               at android.os.Handler.dispatchMessage(Handler.java:95)**
**               at android.os.Looper.loop(Looper.java:154)**
**               at android.app.ActivityThread.main(ActivityThread.java:6119)**
**               at java.lang.reflect.Method.invoke(Native Method)**
**               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)**
**               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)**
**I/System.out: failure, exception = com.twitter.sdk.android.core.TwitterApiException: HTTP request failed, Status: 400**

This is strange the exception tells me its 400, but the api exception Stacktrace tells me its 403.

whats going on here?


#5

And also i have tried Twitter4j which leaves me with the same error message.

this is my Twitter4j implementation:

ConfigurationBuilder builder;
builder = new ConfigurationBuilder();
builder.setApplicationOnlyAuthEnabled(true);
Twitter twitter = new TwitterFactory(builder.build()).getInstance();
twitter.setOAuthConsumer(RandomStringUtils.randomAlphanumeric(20), RandomStringUtils.randomAlphanumeric(40));
OAuth2Token token = twitter.getOAuth2Token();
Log.d(DEBUG_TAG,"token.getTokenType() = " + token.getTokenType());

And the resulting error message:

W/System.err: 403:The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits (https://support.twitter.com/articles/15364-about-twitter-limits-update-api-dm-and-following).
W/System.err: message - Unable to verify your credentials
W/System.err: code - 99
W/System.err: Relevant discussions can be found on the Internet at:
W/System.err: 	http://www.google.co.jp/search?q=13ec0412 or
W/System.err: 	http://www.google.co.jp/search?q=15971965
W/System.err: TwitterException{exceptionCode=[13ec0412-15971965], statusCode=403, message=Unable to verify your credentials, code=99, retryAfter=-1, rateLimitStatus=null, version=4.0.6}
W/System.err:     at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:164)
W/System.err:     at twitter4j.HttpClientBase.request(HttpClientBase.java:57)
W/System.err:     at twitter4j.HttpClientBase.post(HttpClientBase.java:86)
W/System.err:     at twitter4j.auth.OAuth2Authorization.getOAuth2Token(OAuth2Authorization.java:66)
W/System.err:     at twitter4j.TwitterBaseImpl.getOAuth2Token(TwitterBaseImpl.java:390)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$override.downloadHTML(MainActivity.java:51)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$override.static$access$000(MainActivity.java:21)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$override.access$dispatch(MainActivity.java)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity.access$000(MainActivity.java:0)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$1$override.doInBackground(MainActivity.java:35)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$1$override.access$dispatch(MainActivity.java)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$1.doInBackground(MainActivity.java:0)
W/System.err:     at stuff.keltik85.com.mydownloader.MainActivity$1.doInBackground(MainActivity.java:29)
W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:305)
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
W/System.err:     at java.lang.Thread.run(Thread.java:761)

#6

OMG i found the problem.

you have to register at https://dev.twitter.com/apps to get the Consumer Key and Secret. You cant just genereate a Random String and use it as Consumer key and secret.

The documentation is unclear about that in my opinion.


#7

Ah - yes, absolutely you need an app consumer key and token.

I’d be happy to clarify the documentation. Where would you suggest this should be made more clear (documentation page links?). Sorry you were confused about this!


#8

thanks for some feedback. No need to be sorry for that.

I think an entry on this page https://dev.twitter.com/oauth/application-only under the paragraph Issuing application-only requests as a Step 0 would be appropriate. Something along these lines:

Step 0:
To obtain a Consumer and Secret Key go to the page: https://dev.twitter.com/apps
Input the stuff there and obtain the keys…

(this is not really meant to be copy&pasted into the docs)


#9

Got it - thanks for the suggestion.