Subscribe to Martyr2's Programming Underground        RSS Feed
-----

Demo of Twitter Application-Only OAuth Authentication Using Java

Icon 2 Comments
I found that there was little in the way of examples using Application-Only OAuth for Twitter using Java. So I thought I would put together the basics for those looking for the same thing. This demo example below shows you how to acquire a bearer token and then using that token to issue requests to Twitter's REST API version 1.1. However, only endpoints that don't need to have a user account can be used. This means that the demo can primarily use those endpoints which list publicly accessible tweets, lists or user information.

Twitter's Two Types of Authentication

Twitter features two different types of authentication. The first type is user authentication (OAth Signed) which allows an application to act on behalf of the user, as the user. When it comes to issuing a command, such as creating or editing status tweets, you would need to use this type of authentication. If that is the type of program you need to create, consider reading the Twitter section on obtaining access tokens for this type of access.

The second type of authentication, which this demo shows how to use, is application-only authentication. This type of access doesn't need a program to login as a specific user. This method is for programs that just need to access public information. Examples of this type of information are tweets and lists in pretty much a read only environment. This authentication scheme is great for widgets, tweet readers, and other projects that don't need to act on behalf of a specific user.

Before using a specific endpoint URL, be sure to check which type of authentication scheme it needs to use. But the quick way to think about it is to ask yourself "Would I have to login to twitter to do this action?" If the answer is yes, then you know you need the user authentication model.

The Authentication Process

The process for Application only authentication is relatively simple. It goes through the following steps:


1. Register with Twitter to get a consumer key and consumer secret.
2. Combine the key and secret together and encode it with a base64 encoding.
3. Use that new encoded key to ask Twitter for a bearer token.
4. Get the token back from Twitter, save it and then supply it in the headers of additional requests.


After you have gotten your consumer key and secret, we have to create a function that will take both, meld them together and encode them. But Java doesn't come with a standard way to encode into base64. For this we decided to use Apache Commonds Codec to encode the keys. Once you download and add the jar to your project, you can then use the encoder to encode our key and secret.

// Encodes the consumer key and secret to create the basic authorization key
private static String encodeKeys(String consumerKey, String consumerSecret) {
	try {
		String encodedConsumerKey = URLEncoder.encode(consumerKey, "UTF-8");
		String encodedConsumerSecret = URLEncoder.encode(consumerSecret, "UTF-8");
		
		String fullKey = encodedConsumerKey + ":" + encodedConsumerSecret;
		byte[] encodedBytes = Base64.encodeBase64(fullKey.getBytes());
		return new String(encodedBytes);  
	}
	catch (UnsupportedEncodingException e) {
		return new String();
	}
}



Here we take in the key and secret, concatenate them together with a colon and then encode them using our Base64 object we got from the Apache Commons Codec package. Here we encoded them as UTF-8 encoding and return the encoded string. If we get the rare unsupported encoding exception, we will return a blank string.

Now that we have our encoded key (stored in a variable called encodedCredentials) it is time to request our bearer token from Twitter. To do that we are going to open up a secure SSL connection to Twitter's authentication URL and supply it with the encoded key string in the Authorization header. If everything goes through correctly, it will return the token in the form of a Javascript Notation (JSON) object. Below is how we are going to do this...

// Constructs the request for requesting a bearer token and returns that token as a string
private static String requestBearerToken(String endPointUrl) throws IOException {
	HttpsURLConnection connection = null;
	String encodedCredentials = encodeKeys("<consumerkey>","<consumersecret>");
		
	try {
		URL url = new URL(endPointUrl); 
		connection = (HttpsURLConnection) url.openConnection();           
		connection.setDoOutput(true);
		connection.setDoInput(true); 
		connection.setRequestMethod("POST"); 
		connection.setRequestProperty("Host", "api.twitter.com");
		connection.setRequestProperty("User-Agent", "Your Program Name");
		connection.setRequestProperty("Authorization", "Basic " + encodedCredentials);
		connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"); 
		connection.setRequestProperty("Content-Length", "29");
		connection.setUseCaches(false);
			
		writeRequest(connection, "grant_type=client_credentials");
			
		// Parse the JSON response into a JSON mapped object to fetch fields from.
		JSONObject obj = (JSONObject)JSONValue.parse(readResponse(connection));
			
		if (obj != null) {
			String tokenType = (String)obj.get("token_type");
			String token = (String)obj.get("access_token");
		
			return ((tokenType.equals("bearer")) && (token != null)) ? token : "";
		}
		return new String();
	}
	catch (MalformedURLException e) {
		throw new IOException("Invalid endpoint URL specified.", e);
	}
	finally {
		if (connection != null) {
			connection.disconnect();
		}
	}
}



At this point it became clear that we needed to find a way to be able to digest the JSON responses that Twitter is going to give us after we make the request. For this problem we brought in Google's JSON-Simple package. We had originally considered using Google's GSon but we needed something that would simply encode the result into an array or object without knowing much about the result's structure. This is because Twitter makes it clear that the structure changes and some fields may be out of order or simply not existent. This makes it difficult to use GSon which requires casting to specific classes.

So with this code we ask Twitter to give us the bearer token by opening up the connection, posting the appropriate headers through a POST request and in the body specifying client credentials as the grant type. We submit this request to Twitter's POST oauth2/token endpoint URL. It then replies with the bearer token which we fetch from the object given to us using the JSONValue object (supplied by the JSON-Simple package).

Ok, we now have the bearer token and so we will save this and use it for additional requests. In the function below we are going to ask for the first two tweets supplied by the twitter account @twitterapi.

// Fetches the first tweet from a given user's timeline
private static String fetchTimelineTweet(String endPointUrl) throws IOException {
	HttpsURLConnection connection = null;
				
	try {
		URL url = new URL(endPointUrl); 
		connection = (HttpsURLConnection) url.openConnection();           
		connection.setDoOutput(true);
		connection.setDoInput(true); 
		connection.setRequestMethod("GET"); 
		connection.setRequestProperty("Host", "api.twitter.com");
		connection.setRequestProperty("User-Agent", "Your Program Name");
		connection.setRequestProperty("Authorization", "Bearer " + bearerToken);
		connection.setUseCaches(false);
			
			
		// Parse the JSON response into a JSON mapped object to fetch fields from.
		JSONArray obj = (JSONArray)JSONValue.parse(readResponse(connection));
			
		if (obj != null) {
			String tweet = ((JSONObject)obj.get(0)).get("text").toString();

			return (tweet != null) ? tweet : "";
		}
		return new String();
	}
	catch (MalformedURLException e) {
		throw new IOException("Invalid endpoint URL specified.", e);
	}
	finally {
		if (connection != null) {
			connection.disconnect();
		}
	}
}



In the code above we make another request, this time a GET request, to Twitter using the URL https://api.twitter....tterapi&count=2 which will show us two tweets from the twitterapi account. The sample itself just grabs the first tweet however in case you were wondering. It takes the response, converts it to an object that we can get at using standard java.util.map and java.util.list get() method calls. We get at the first item and then access the value for that item's "text" key and returns it. This is the text of the tweet. If the item is not found, it will return null and in that case we return an empty string.

The last thing we need for this program is some helper functions readResponse() and writeRequest(). I won't go into these methods much because they are simply stream reading and writing routines that are self explanatory.

// Writes a request to a connection
private static boolean writeRequest(HttpsURLConnection connection, String textBody) {
	try {
		BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
		wr.write(textBody);
		wr.flush();
		wr.close();
			
		return true;
	}
	catch (IOException e) { return false; }
}
	
	
// Reads a response for a given connection and returns it as a string.
private static String readResponse(HttpsURLConnection connection) {
	try {
		StringBuilder str = new StringBuilder();
			
		BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
		String line = "";
		while((line = br.readLine()) != null) {
			str.append(line + System.getProperty("line.separator"));
		}
		return str.toString();
	}
	catch (IOException e) { return new String(); }
}



The Summary

With the encodedKeys() function we took our key and secret and put them together and encoded them. We then took that string, supplied it to Twitter's oauth2/token endpoint URL via a POST request to get back a bearer token. Once we had the token we saved it and used it in a GET request to @twitterapi's timeline to get at their tweets. To help us easily process the JSON responses back from twitter we used Google's JSON-Simple package which took the JSON and built objects we could then use to get at the info.

Given these functions we can easily build more functionality for issuing other requests on behalf of the user as an application. We hope that has proved useful to you and helps you all build great little Twitter apps using Java.

Don't forget to purchase our ebook which contains over 200 miscellaneous project ideas which contains projects for all levels and languages.

Thanks again for reading! :)

2 Comments On This Entry

Page 1 of 1

Narek Babadjanyan Icon

06 May 2013 - 09:40 AM
Thanks for the tutorial, OAuth is really a PITA if you don't get the hang of it. I don't know what happens when you DO get the hang, I have never made it to the point :D
1

Martyr2 Icon

06 May 2013 - 11:14 AM
Thanks for the comment Narek. You are right, but I find that Twitter has done a good job of explaining the OAuth process they use and the documentation has really been well written for interacting with their service. It is part of why I did the demo with Twitter so that people could look at my code and compare it with the docs over at Twitter to see how the pieces fit together. :)
0
Page 1 of 1

April 2014

S M T W T F S
  12345
6789101112
13141516 17 1819
20212223242526
27282930