Brain Flush

May 3, 2009

Introducing Signpost: Easy OAuth for Java and Apache HttpComponents (Android, too)

Filed under: Software Development & Programming — Tags: , , , , , , , — Matthias @ 10:58 am

I would like to announce a project I started, which I hope may be useful to Java (particularly Google Android) application developers who need to communicate with web services that leverage the OAuth protocol for accessing protected resources.

What is Signpost?

Signpost is the easy and intuitive solution for signing HTTP messages in conformance with the OAuth Core 1.0 standard. Signpost has been designed to work in conjunction with the Apache HttpComponents library, a proven, well-established HTTP library for the Java programming language.

Signpost is still in beta stage, which means it may contain bugs. The project is currently hosted at Google Code and can be downloaded, distributed and used under the terms of the Apache License, version 2.

Why another OAuth library for Java?

It was my discontendness with Netflix’s OAuth implementation which ultimately drove me to develop my own solution. My biggest gripes with it were:

  • Its clumsy, overly complicated API
  • Its tendency to do more than what’s actually in the standard (why does it implement an own HTTP layer? OAuth is about message signing, not about message sending)
  • Its limitations resulting from the last point, particularly:
    • Its ignorance towards RESTful web services (a 201 is treated as an error)
    • Its inability to process other HTTP verbs than GET (you must subclass in order to POST or PUT a resource)
    • Its inability to send more complex messages (don’t even try to send multipart requests)

Signpost attempts to avoid these issues as described below (a brief remark: Despite those issues, I highly appreciate Netflix’s work on the original implementation. In fact, Signpost is to some degree based on code from the reference implementation).

Goals of Signpost

Signpost has been designed with several principal goals in mind:

Simplicity

Using Signpost is as simple as it could possibly get — all actions are executed with only a few lines of code. For example, here is how you would sign an HTTP message using Signpost (assuming you have already created the involved HttpClient and OAuthConsumer objects):

        // create an HTTP request to a protected resource
        HttpGet request = new HttpGet("http://example.com/protected");

        // sign the request (consumer is a Signpost OAuthConsumer)
        consumer.sign(request);

        // send the request
        HttpResponse response = httpClient.execute(request);

Signpost exposes a minimalistic API designed for two purposes: Signing HTTP messages and requesting tokens from an OAuth service provider. Everything else is beyond the scope of the OAuth specification, and is thus left to the HTTP messaging layer, where it belongs.

For more exhaustive examples, please refer to GettingStarted.

Unobtrusiveness

Signpost tries to be as unobtrusive as possible. Unlike the OAuth reference implementation for Java, Signpost does not wrap the entire HTTP layer and hides its features from the client. Instead, you simply pass an HttpRequest object to it, and Signpost will sign the message using the credentials it was configured with. This means that all the power and flexibility of the Apache HttpComponents? is still at your fingertips!

Limitations

Simplicity doesn’t come free. Thus, Signpost currently makes certain assumptions to reduce the complexity of both the implementation and the API.

Deviations from the OAuth standard

  • Additional service provider parameters for retrieving request tokens are currently unsupported (cf. section 6.1)
  • Message signing using public key encryption (as per section 9.3) is currently unsupported. Message signing using the PLAINTEXT and HMAC-SHA1 is supported, however.
  • The OAuth standard demands that OAuth request parameters may be put in the URI query string or in the message payload. Signpost will never do that; instead, all OAuth protocol parameters are written to the HTTP Authorization header field. Anything you put there will be overwritten by Signpost.
  • Signpost does not support writing OAuth protocol params to the WWW-Authenticate header field

I believe that even with those restrictions in place, Signpost will work for 99% of its users. Trading in some flexibility only relevant for edge cases was a design decision. If that doesn’t work for your setup, then Signpost is probably not the best choice.

Thread Safety

Signpost is not thread safe and probably will never be. Signpost objects are very lightweight, so you are adviced to create an OAuthConsumer and OAuthProvider for every thread in your application that must send signed HTTP requests.

Google Android

Signpost works flawlessly in conjunction with Android, Google’s software stack for mobile devices. In fact, Signpost has already signed thousands of HTTP requests at this very moment, as it is an integral part of Qype Radar, our geo-sensitive mobile application for Android that finds the best places near you.

Since Android already ships with a recent version of the Apache HttpComponents?, you merely need to add the Signpost JAR to your Android application, and you’re all set.

Advertisements

8 Comments »

  1. This looks great: I love a minimal API! I’m planning on adding OAuth support to my Twitter app soon, so this should be very handy!

    Comment by JJC1138 — May 7, 2009 @ 2:33 am

    • Good to hear! I’m quite eager to hear whether it works with Twitter (haven’t tested yet). Please let me know should any defects / incompatibilities surface, and I’ll try to address them ASAP.

      Comment by Matthias Käppler — May 7, 2009 @ 8:19 am

  2. Pretty kewl. Anything simple andl ightweight is always good.
    Is it possible though to make the http client pluggable (HttpClient interface)?
    E.g HttpUrlConnection, commons httpclient, jetty httpclient, etc (for users who prefer other httpclients)

    Comment by ct — May 24, 2009 @ 5:51 pm

    • Actually, I thought about that as well. Signpost first and foremost had been created to work for our setup here at Qype. However, I definitely see the need for it to be able to work in environments that do not make use of the Apache Commons HTTP libraries in order to be actually useful for other developers.

      I’ll create a ticket for this, but I’m not sure how soon I can get this done (I only work on this library in my spare time now). In particular, when I provide the interface abstractions, I would appreciate to see contributions from the community when it comes to adapter implementations (e.g. for the Jetty stuff).

      Comment by Matthias Käppler — May 25, 2009 @ 8:51 am

  3. Thank you. I’m looking forward to trying it out.

    Comment by Anonymous — January 23, 2010 @ 12:00 pm

  4. Ha, was looking for existing Android OAuth stuff today before rolling my own, and who did I find that had already done it, Matthias!

    Thanks Matthias.

    Comment by Charlie Collins — March 16, 2010 @ 10:29 am

    • Haha, hey Charlie! Android land is small I guess ;-) You may want to wait for the maintenance release though, I managed to break callbacks with the 1.2.1 release. That stuff happens if you try to close all tickets on a Friday afternoon. Duh.

      Comment by Matthias Käppler — March 16, 2010 @ 9:32 am

  5. Thanks Matthias. I wasted a lot of time with the Netflix OAuth stuff until I found your code. It worked first time.

    Comment by Warwick Hunter — June 20, 2011 @ 6:28 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: