Reputation: 63
I've got an example web.py app supplying REST services + OAuth2. In Python, a client app goes through the process of generating an OAuth2 consumer, request, signing it, etc. something like this (pseudo code reference, not complete):
import json
import time
import oauth2
import urllib2
# Set up the POST variables
method = 'POST'
url = 'https://localhost/service/rest'
parameters = {
'username' : username,
'password' : password
}
# Generate our Consumer object
consumer = oauth2.Consumer( key = KEY, secret = SECRET )
# Add additional parameters required by OAuth
parameters['oauth_version'] = "1.0"
parameters['oauth_nonce'] = oauth2.generate_nonce()
parameters['oauth_timestamp'] = int(time.time())
parameters['oauth_consumer_key'] = consumer.key
# Generate and sign the request
oauth = oauth2.Request( method = method, url = url, parameters = parameters )
signature_method = oauth2.SignatureMethod_HMAC_SHA1()
oauth.sign_request( signature_method, consumer, None )
# Shoot it off to the webserver
req = urllib2.Request( BASE_URL, oauth.to_postdata() )
result = urllib2.urlopen( req ).read()
json_result = json.loads( result )
print json_result
TADA! It works like a champ. I'm trying to do the same thing under Java, well specifically on Android, but I'll take anything at this point. All the examples I've seen are focused on public OAuth2 APIs using three-legged auth or are focused on server side configurations for web-services.
Can someone take pity on me and point me to an equally simple example in Java using BasicHttpContext, DefaultHttpClient and friends?
EDITED LATER
It's probably considered bad form to answer your own questions, but here is how to do what I was asking. It turns out that two-legged oauth is really OAuth v1.0 functionality, so the semi-abandoned oauth.signpost library can do it easily. I tried to use the more recently maintained joauth library, but couldn't find any good examples of how to do just the bits I wanted. This code is actually spread around in three or four different java files in my code, but I did it all together for this pseudo code example.
import ...
import oauth.signpost.OAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.exception.OAuthCommunicationException;
import oauth.signpost.exception.OAuthExpectationFailedException;
import oauth.signpost.exception.OAuthMessageSignerException;
public class RestClient {
private OAuthConsumer oauth_consumer = null;
private DefaultHttpClient http_client;
private static final String consumer_key = "something";
private static final String consumer_secret = "something_else";
public RestClient( Context context ) {
// Instantiate our custom http client with our trusted key
this.http_client = new DefaultHttpClient();
// Instantiate an oauth_consumer
this.oauth_consumer = new CommonsHttpOAuthConsumer( consumer_key, consumer_secret );
}
public POST( String url, Map params ) {
// Initialize our post request
HttpPost httppost = new HttpPost( url );
httppost.setHeader("Accept", "application/json");
httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
// This iterates through the parameters and stores them for use
List<NameValuePair> name_value_pairs = new ArrayList<NameValuePair>(2);
Iterator iter = params.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry pairs = (Map.Entry)iter.next();
name_value_pairs.add(
new BasicNameValuePair( (String)pairs.getKey(), (String)pairs.getValue() )
);
}
try {
// Put our parameters in our Post
httppost.setEntity( new UrlEncodedFormEntity( name_value_pairs ) );
// sign our request
this.oauth_consumer.sign( httppost );
// Yoiks, and away!
HttpResponse response = http_client.execute( httppost );
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
JSONObject json = new JSONObject( convertStreamToString(instream) );
// Closing the input stream will trigger connection release
instream.close();
return json;
} catch ( aBunchOfShit e) {
e.printStackTrace();
}
}
return null;
}
}
When you verify your signature on the backend, be sure to include all the parameters you passed in the request. I sat looking at the "Invalid signature. Expected signature base string POST&..." error for an hour until I figured out how to set System.setProperty("debug","1"); and saw the original base string on the Java side. This works good enough for now, but I'd still like to see how it works under a maintained library.
Upvotes: 1
Views: 2711
Reputation: 89209
Since you've mentioned about joauth, I have written a documentation to allow OAuth 1 authorization using JOAuth.
I hope this helps you.
Upvotes: 1