By far the most popular post on this blog is the one regarding using OAuth and Java. At that time OAuth, was still fairly new and I was interested in using the Java implementation with some Android applications I had been working on. The Java reference implementation was new, difficult to build, sparsely documented, and the API was confusing to say the least. Months passed and very little was done to the library. I would probably attribute this to the lack of OAuth enabled web services. Public key signing was added eventually, but when Android upgraded to HttpClient 4.0, it broke compatibility with the original OAuth library. A ported version was eventually added to the repository by Sean Sullivan but the library was still fairly difficult to use. I, like many people, swore that I would eventually get around to eventually writing a Java OAuth library that was straight forward and easy to use.

Fortunately for us, Matthias Kappler has written an excellent library called Signpost that uses the standard Java URL class, and also supports HttpClient requests. Signpost does not attempt to perform both signing and requesting like the original library and focuses solely on token acquisition and request signing, which really should be the key parts of any implementation. There are many examples of using Signpost with a number of services, including Twitter and using the new OAuth 1.0a spec that addresses the vulnerability found in the OAuth spec recently.

You can go to the google code site to check out the library and the basics of token request and authorization (including the new “pin” authorization), but I will show you some quick code to perform a status update request with Twitter. This code assumes that you have a valid access token and secret.

Update the user’s status using URL:


       OAuthConsumer consumer = new DefaultOAuthConsumer(
                "yourappkey",
                "yourappsecret",
                SignatureMethod.HMAC_SHA1);
        OAuthProvider provider = new DefaultOAuthProvider(consumer,
                "http://twitter.com/oauth/request_token",
                "http://twitter.com/oauth/access_token",
                "http://twitter.com/oauth/authorize");
        consumer.setTokenAndSecret(AUTH_TOKEN,TOKEN_SECRET);//load these from a db or file
        URL url = new URL("http://twitter.com/statuses/update.xml?status=" + URLEncoder.encode("test one two three"));
        HttpURLConnection request = (HttpURLConnection) url.openConnection();
        request.setRequestMethod("POST");
        consumer.sign(request);
        request.connect();
        if(request.getResponseCode() == 200)
           return true;
       else
           return false;

Performing a status update using HttpClient, assumes mClient is an already initialized HttpClient and excludes exception handling code:


       OAuthConsumer consumer = new DefaultOAuthConsumer(
                "yourappkey",
                "yourappsecret",
                SignatureMethod.HMAC_SHA1);
        OAuthProvider provider = new DefaultOAuthProvider(consumer,
                "http://twitter.com/oauth/request_token",
                "http://twitter.com/oauth/access_token",
                "http://twitter.com/oauth/authorize");
        consumer.setTokenAndSecret(AUTH_TOKEN,TOKEN_SECRET);//load these from a db or file
            Uri.Builder builder = new Uri.Builder();
            builder.appendPath("statuses").appendPath("update.json")
                    .appendQueryParameter("status", status);
            Uri man = builder.build();
            HttpPost post = new HttpPost("http://twitter.com"  + man.toString());
            consumer.sign( post);
            HttpResponse resp = mClient.execute(post);
            if (resp.getStatusLine().getStatusCode() == 200) {
                    return true;
                } else {
                    return false;
                }

Hopefully you will also find Signpost to be as useful as I did. I was able to migrate my twitter application from using basic authentication to using OAuth with Signpost in an hour compared to the hours of pain spent trying to use the original implementation.

Posted on June 27th, 2009 | Filed under identity, java | 1 Comment »

Twitter recently made a streaming API available that allows developers to get real-time status updates using HTTP streaming. You can read about the specifics of the API here. There are a few different levels of streaming that developers can use, most of the more heavyweight streams require explicit permission and some kind of agreement with Twitter. Streams are available in JSON and XML, you can also get a delimited stream which tells you how many bytes each status uses to make I/O a little easier. I am going to show you how to use Apache HttpClient 4.0 and the XPP XML Pull Parser library to write a simple client to consume the publicly available “spritzer” stream.

Setting Up The Client
The first step is to set up the HTTP client. The API uses your twitter username and password with basic authentication to authenticate. We will configure our HttpClient with our twitter user name and password as the credentials for the “stream.twitter.com” scope.


        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "utf-8");

         SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

         ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params,
                registry);
        DefaultHttpClient client = new DefaultHttpClient(manager, params);

        client.getCredentialsProvider().setCredentials(new AuthScope("stream.twitter.com", 80),
                new UsernamePasswordCredentials("username", "password"));

Requesting And Parsing
Next we will create the Get request for the “spritzer” stream and perform the request. After that we will open a pull parser on the network stream and “pull” the xml from the stream as it comes in.

Each status update comes in the format:


<?xml version="1.0" encoding="UTF-8"?>
<status>
....
</status>

It is important to note that each status has the xml document tag at the beginning.

Most of the parsing code is the result of a lot of trial and error so it is not the prettiest. See the comments towards the bottom for some important comments about the implementation.


        HttpGet get = new HttpGet("http://stream.twitter.com/spritzer.xml");
        try {
            HttpResponse resp = client.execute(get);
            int statusCode = resp.getStatusLine().getStatusCode();

        if (statusCode == 200) {
                InputStream stream = resp.getEntity().getContent();
                XmlPullParserFactory factory;
                factory = XmlPullParserFactory.newInstance();
                XmlPullParser parser = factory.newPullParser();

                parser.setInput(stream, "utf-8");
                while (true) {
                    int event = parser.next();
                    if (event == XmlPullParser.START_TAG) {
                        String name = parser.getName();
                        if (name.equals("status")) {
                            String text = null;
                            String screenName = null;
                            while (true) {
                                event = parser.next();
                                if (event == XmlPullParser.START_TAG) {
                                    name = parser.getName();
                                    if (name.equals("text")) {
                                        text = parser.nextText();
                                    } else if (name.equals("user")) {
                                        String userName;
                                        while (true) {
                                            int eventUser;
                                            eventUser = parser.next();
                                            userName = parser.getName();
                                            if (eventUser == XmlPullParser.START_TAG) {
                                                if (userName.equals("screen_name")) {
                                                    screenName = parser.nextText();
                                                }
                                            } else if (eventUser == XmlPullParser.END_TAG
                                                    && userName.equals(("user"))) {
                                                break;
                                            }
                                        }
                                    }
                                } else if (event == XmlPullParser.END_TAG
                                        && parser.getName().equals("status")){
                                    break;
                                }

                            }
                            //output username and status to console, you will want to parse and dispatch whatever
                            //information you need to something that does something a bit more substantial

                            System.out.println(screenName + ": " + text); //insert money making method here

                            //IMPORTANT HACK
                            //because each stream starts with an <xml/> document tag
                            //we have to reset the input of the parser to the stream
                            parser.setInput(stream, "utf-8");
                        }
                    } else if (event == XmlPullParser.END_TAG
                            && parser.getName().equals("statuses"))
                        break;

                }

            }

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }

Here is the entire source you should be able to build it and run it in the console without many problems, but remember never try to actually read the stream.

stream

Posted on June 22nd, 2009 | Filed under Uncategorized | No Comments »

Android 1.1 was released this week and included a voice search application as part of the update. Like most parts of Android the speech recognition functionality has been abstracted into sub tasks that use intents to perform specific actions. You can now call an intent that will launch the speech recognizer “application” and return to your application a list of results. The Intent and a description of it’s results can be found in the Android source code in the android.speech package. This library is not officially supported by the Android SDK and it should not be used in any consumer facing applications. That said you should also make sure to include “” in your application’s manifest file so that the app cannot be installed on a phone that doesn’t have the 1.1 firmware on it.

Here is the code for launching a simple speech recognition intent:


Intent intent = new Intent("android.speech.action.RECOGNIZE_SPEECH");
startActivityForResult(intent, 0);

The intent launches the voice recognition activity which prompts the user to speak into the phone, your speech is then analyzed and a list of results is returned in a bundle to your activity.

Here is the code for extracting the results:


@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		...code for checking resultCode and data intent...
	ArrayList<String> results = data.getExtras().getStringArrayList("results");

	}

As you can see this makes it very easy to add a speech recognition element to an application, although I am not sure whether or not this functionality will be officially supported in a future version of the SDK.

h1h2h3h4

Posted on February 10th, 2009 | Filed under android, java | 1 Comment »

The G1 came out this week and I have been putting it through the paces. I really like the seamless transition between developing with the emulator and developing on the device. I think overall it is a very strong first device for Android, but I think that normal users may not recognize some of the more powerful features of the platform.

The Intent system allows for applications and activities to interact with each other, so that you can have applications using the features of other applications. I think this is a really interesting concept and think it could lead to a less application-centric view of phone operation towards a more feature-centric view. Instead of developing an entire application, developers can develop specific features that perform a very specific task. These features can be used by other applications to create new and interesting functionality.

I think the best example of this concept is Barcode Scanner. Barcode Scanner is the application specific manifestation of ZXing which I blogged about previously. Installing it lets you scan bar and QR Codes and lets you perform search actions or interact with the results(like an e-mail address or phone number). The two shopping applications CompareAnywhere and ShopSavvy use the ZXing library themselves for doing barcode scanning, but they include the ZXing library as part of their application bundle.

In my previous entry I mentioned that I would like to see specific Intents that let you use the encoding and decoding ability of ZXing from other applications and the ZXing team responded that the latest build had this exact functionality! Now all you have to do is install Barcode Scanner on your phone and your applications can take advantage of its features. Specifically, it provides Intents that allow your application to use the encoding and decoding functionality. The Intent mechanism makes it almost too simple to integrate this functionality into your application.

Encoding – “com.google.zxing.client.android.ENCODE”

To encode a string into a QR Code Simply create an Intent with the Decode action specified, two string extras specifying the Type and Data and call startActivity():


Intent intent = new Intent("com.google.zxing.client.android.ENCODE");
				intent.addCategory(Intent.CATEGORY_DEFAULT);
				intent.putExtra("ENCODE_TYPE", "TEXT_TYPE");
				intent.putExtra("ENCODE_DATA","HELLO WORLD");
startActivity(intent);

The string values for the Intents and the extras values can be found in the Intents and Content classes in the ZXing source code.

Decoding – “com.google.zxing.client.android.SCAN”

Bringing up the decoding camera interface is just as easy as encoding with the added step of having it return the decoded value of the barcode to our main application.


Intent intent = new Intent("com.google.zxing.client.android.SCAN");
				intent.addCategory(Intent.CATEGORY_DEFAULT);
				startActivityForResult(tent,0);

The big difference here is that we are using startActivityForResult which will allow the scanning activity to return the results of the scan back to our app. In the Activity that launched the decode intent we can extract the results of the scan in the onActivityResult method by simply accessing the string extra “SCAN_RESULT”.


data.getStringExtra("SCAN_RESULT");


You can now use these features to do all kinds of interesting things. I am currently interested in transferring data between phones by encoding the data in a QR code and having the other phone retrieve it by simply pointing it at the other camera’s screen. You could also encode movie ticket information into a QR code and have it displayed on the phone so it can be scanned at the theater.

I hope this post showed you how useful Barcode Scanner can be for your application and it’s users. Now if someone could do something about the reviewers in the android app store…..

Posted on October 23rd, 2008 | Filed under Uncategorized | 3 Comments »

Long since the radical ideas of the 60s (and the namesake of this blog), comes a walking house!

Posted on October 23rd, 2008 | Filed under Uncategorized | No Comments »

I have put together a page with some pictures and descriptions of the applications I have been prototyping for Android lately.  They also include a few screen shots of the application I entered into the Android Developer Challenge.  If there is any interest in any of the technical aspects of these applications I would be more than happy to make a post about how they work.

Android Applications and Ideas

Here are a few screen shots to make this post more interesting:

Posted on September 22nd, 2008 | Filed under Uncategorized | No Comments »

QR Codes are a great way to share information with mobile phones. Originally used to track car parts, QR codes are now used to quickly and easily spread information to mobile users. For example a company can put a QR code in a magazine that contains the URL to their website. Instead of the user having to type in a long URL on their phone they can simply take a picture of the QR Code with their camera phone and have their decoding software open the link for them. For more uses of QR Codes check out this blog.

I am going to go through a quick example of encoding and decoding QR codes in Android.

Encoding

There are a number of services and libraries available for encoding QR Codes. The actual encoding process is a bit more involved than I would like to go through for this entry and we generally would not want to do the actual encoding on the client. Instead we will harness the power of the “cloud” to do the heavy lifting for us. In this case we will use the Google Charts API which just recently expanded to include QR codes. The API allows for a number of options such as size, error correction type, encoding type, and margins (the general rule for QR Codes is to have a 4 column/row white border around the barcode so that the decoding software can get a better “lock” on it)

The code below makes an http request to the Google Charts API with the URL encoded text we entered in the EditText view and populates our ImageView with the resulting image.


encodeButton.setOnClickListener(new OnClickListener(){

public void onClick(View arg0) {
    img.setImageBitmap(QR.this.encodeString(edit.getText().toString()));
}

});

private Bitmap encodeString(String input) {
     URL aURL;
     try {
      aURL = new URL("http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF- 8chl="+URLEncoder.encode(input, "UTF-8"));
      URLConnection conn = aURL.openConnection();
      conn.connect();
      InputStream is = conn.getInputStream();
      BufferedInputStream bis = new BufferedInputStream(is);
      Bitmap bm = BitmapFactory.decodeStream(bis);
      bis.close();
      is.close();
      return bm;
      } catch (MalformedURLException e) {
       e.printStackTrace();
      } catch (IOException e) {
       e.printStackTrace();
      }
     return null;
}

Decoding

The ZXing library is an open source Java library for decoding numerous 1D and 2D barcodes. We will be using the core library but there is also an Android specific application that provides hooks into the camera. Since the emulator does not support capturing images just yet we will settle for using the image we just encoded. We will need one class specific to the Android ZXing library, RGBMonochromeBitmapSource which lets us convert Android bitmaps to the format that ZXing uses.

The code below takes the bitmap image from the ImageView and pushes it through the decoder populating a TextView.


decodeButton.setOnClickListener(new OnClickListener(){

public void onClick(View arg0) {

     try {
      tv.setText(((QR.this.decode(img.getDrawingCache()))));
     } catch (ReaderException e) {
      e.printStackTrace();
     }
}
});

private String decode(Bitmap bm) throws ReaderException {
     QRCodeReader reader = new QRCodeReader();
     Result r = reader.decode( new RGBMonochromeBitmapSource(bm));
     return r.getText();
}

We can use our friend Linkify to automatically make any text of the correct format (http://, mailto:, and even map locations) into a link that launches the appropriate application.


textView.setAutoLinkMask(Linkify.ALL);



I have even been experimenting with integrating the decoder with the built in WebView class which lets us decode images directly from the web browser. As you can see in this example I have clicked on a QR Code and a dialog pops up with the decoded information.

The code to do this is a little hackish but involves using the WebView.requestImageRef(msg) mechanism and calling decode from the handler that receives that message.

I know of a number of decoders being developed for android but hopefully there will be a standard one that can be called using Intents so that developers can just fire off an intent in their application and get text back, not having to worry about dealing with the camera or the decoder libraries.

Posted on August 25th, 2008 | Filed under android, java, mobile | 1 Comment »

I have been learning Scala recently and have been trying to solve various coding challenges in it.  I have the beta version of the Scala book from Artima and it does a really good job of teaching you the low level aspects of the language as well as encourage you to think and do things in a “Scala way.”  Today I read over a blog post about a grad student at Rutgers who found a new prime-generating formula.  You can read the blog for the details about the formula.  Here is my implementation in Scala (I am not a functional programming or Scala expert so there may be something gravely wrong with my implementation):


def numSeq(n:Int):Stream[Int] = Stream.cons(n, numSeq(n+1))

def gcdLoop(x: Int, y: Int): Int = {
var a = x
var b = y
while (a != 0) {
val temp = a
a = b % a
b = temp
}
b
}
//or
def gcd(x: Int, y: Int): Int =
if (y == 0) x else gcd(y, x % y)

def a(n:Int):Int = if(n == 1) 7 else a(n-1) + gcd(n,a(n-1))

def alphaStream(s:Stream[Int]):Stream[Int] =
Stream.cons(a(s.head),alphaStream(s.tail))

def primeDiffStream(s:Stream[Int]):Stream[Int] =
Stream.cons(s.tail.head - s.head, primeDiffStream(s.tail))

val primes = primeDiffStream(alphaStream(numSeq(1)))

primes take 100 filter (_ > 1) print

I used streams because I have been reading about stream algorithms (good beginner’s article here) and Streams provide a more efficient way of dealing with large sequences of numbers than lists.  The two gcd methods are taken from the Scala book, another alternative is to use the builtin Int.gcd method. The code can generate the first 5 or 6 primes(with repeats) from the first 25 numbers in the sequence fairly quickly but the gcd method becomes the bottleneck after that.

I have posted the code on gist for anyone that might have any improvements or suggestions: Primes In Scala Gist Snippet
There is also a more straight forward prime stream example in the Scala documentation here.

Posted on July 24th, 2008 | Filed under scala | No Comments »

In case you hadn’t heard, Google has released a preview of AppEngine, it’s cloud/platform service. It provides a full application development and deployment stack that has access to google services like email, login, and datastore. It also provides a python-based application development environment called webapp as well as supporting other python web frameworks, like django.

Since location-based services for mobile phones are all the rage, I thought I would walk through how to create a simple location sharing web service on AppEngine and interact with it in Android. I will show you how to create a simple REST-ish API that consumes HTTP requests and outputs simple XML data. It probably won’t be exciting for people interested in shiny web applications, but using this approach provides a flexible protocol for interacting with remote service from a mobile phone, allowing the data to be consumed and displayed in a native phone application.

After that, I will show you how to use Android’s LBS and networking APIs to interact with the service.

Setup
Create a new AppEngine project and create a file called location.py. First, we need to configure the app.yml with the url mapping for our service. For this example I will simply use “/endpoint” as my mapping to the location.py handler.


application: location
version: 1
runtime: python
api_version: 1

handlers:
- url: /endpoint
  script: location.py

There are many more ways to define your url mapping to provide RESTful urls for your app, see here for more info.

location.py
The source for the service can be found here. I am going to step through the file from the top down.

Model
We want to create a location domain model that can be used with the datastore api. To do this we define a Location class that inherits from db.Model. We will create fields for latitude, longitude, and date.


class Location(db.Model):
  lat = db.IntegerProperty()
  lon = db.IntegerProperty()
  date = db.DateTimeProperty(auto_now_add=True)

lat and lon are stored as Integers because it makes things a little easier to use with some of the Android Map and Location APIs.

Since we want to be able to output our model as XML we make a helper method that makes a one line XML element with lat and lon as attributes:


def printloc(self,location):
      return '<location lat=\'%(lat)s\' lon=\'%(lon)s\'></location>\n' % {'lat':location.lat, 'lon':location.lon} 

Models in AppEngine/webapp have a to_xml() method that allows them to be exported to XML automatically, the format is much more verbose than I would like to deal with in this tutorial, but they do provide an interesting look as to how the data is stored and read in the datastore/BigTable.

Methods
The next two methods get called when a request is made. They are mapped to the GET and POST http methods, this makes it easy to design RESTful interfaces for our web service. In our example we want a POST to create a new location, while GET will fetch a list of the 10 most recent locations.

Post


  def post(self):
      location = Location()
      location.lat = int(self.request.get('lat'))
      location.lon = int(self.request.get('lon'))
      location.put()
      self.response.out.write(self.printloc(location))

This creates a new location object and stores the two parameter values in it and saves the location to the data store. We then write the location out to the response.

The output of this method will look something like this:


<location lat="37422375" lon="-122096532"/>

Get


def get(self):
    locations = db.GqlQuery("SELECT * FROM Location ORDER BY date DESC LIMIT 10")
    self.response.headers['Content-Type'] = 'text/xml'
    self.response.out.write('<list>')
    for l in locations:
        self.response.out.write(self.printloc(l))
    self.response.out.write('</list>')

This code fetches the latest 10 locations using a GQL query and wraps them in a element.

The output of this call will look something like this:


<list>
<location lat="37422375" lon="-122096532"/>
<location lat="37429756" lon="-122100756"/>
<location lat="37428218" lon="-122101459"/>
<location lat="37422383" lon="-122096532"/>
<location lat="37422378" lon="-122096531"/>
<location lat="37422384" lon="-122096533"/>
<location lat="37449370" lon="-122119525"/>
<location lat="37449355" lon="-122119523"/>
<location lat="37454563" lon="-122130219"/>
<location lat="37454443" lon="-122130012"/>
</list>

main


def main():
  application = webapp.WSGIApplication(
                                       [('/endpoint', LocationService)],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
  main()

This code binds our handler to the /endpoint address, and runs the service.

Android integration
I will now briefly demonstrate how to interact with the service from within Android. If you are like me, and were a little late trying to sign up for the AppEngine preview program, you are running your web service locally. You need to run the development server with the “-a ADDRES” where ADDRESS is your internal network address. Android has an internal network loopback that loops any requests made from the phone to “localhost” back to the phone so you won’t be able to access your service if it is running on localhost.

Our first step is to build a new MapActivity that contains a MapView and two menu actions “Update Location” and “Fetch Locations”. The source for this activity can be found here.

Update Location:
The definition of our Post Current Location menu item which is defined inside of public boolean onCreateOptionsMenu(Menu menu):


menu.add(0, 1, "Post Current Location", new Runnable(){

			public void run() {

				// get current location and use it as params to our API call
				LocationManager locMan = (LocationManager) MiniLocationMap.this
						.getSystemService(Context.LOCATION_SERVICE);
				Location loc = locMan.getCurrentLocation("gps");

				 Map headers = new HashMap();

		        String text= "lat=" +(int)(loc.getLatitude()*1E6) + "&lon=" + (int)(loc.getLongitude()*1E6;
		        byte[] bytes = text.getBytes();
		        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
				mRequestQueue.queueRequest(
		                "http://10.0.0.199:8080/endpoint",
		                "POST", headers, new LocationEventHandler(mHandler), bais, bytes.length, false);
			}

		});

This gets your current location in the same way that we did in our fire eagle example. It then constructs a POST request with the latitude and longitude as parameters for our web service. You need to convert the latitude and longitude to integers, there is probably a simpler way to do it than above. This example uses the RequestQueue class which provides an interface for making http requests. For more information on performing these requests you should definitely check out this blog, which is full of great android examples.

The LocationEventHandler class handles the data returned from the request. In my example the EventHandler uses the XML pull parser to parse the XML data into a DemoLocation object which is then passed back to the Map Activity using it’s handler. In the Handler the location is extracted from the Message object and used to center the map on the location just posted:


public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);

			if(msg.what == 123){
				DemoLocation currentLocation = (DemoLocation) msg.getData().get("location");
				mMapController.centerMapTo(new Point(currentLocation.lat, currentLocation.lon), true);

			}
				}
		}

Retrieving Locations


menu.add(0, 0, "Retrieve Locations", new Runnable(){

			public void run() {
				 Map headers = new HashMap();
				mRequestQueue.queueRequest(
		                "http://10.0.0.199:8080/endpoint",
		                "GET", headers, new LocationListHandler(mHandler), null, 0, false);
			}

		});

This creates a GET http request and uses LocationListHandler to create an ArrayList of locations that can be used by our map. To keep the tutorial short I won’t actually do anything with the list of locations, but they could be used with an overlay to draw points on the map of all the places you have recently been.


This fairly primitive implementation should be enough to get you started creating web services in AppEngine and using them in android. Security is obviously an issue I ignored. The built-in google user account api is built around user authentication using web forms and http redirects, similar to OpenID. This makes it a little difficult to create APIs using just google accounts. Implementing OAuth and having the web-based authorizorization part of the process use the google user api, then having a seperate table storing a reference to the user’s account, applications, and access tokens would be one approach to solving this problem.

Overall, AppEngine was easy to use and provides a nice set of functionality to build on top of. Having your web stack and client stack all under the google umbrella is kind of interesting. The barrier of entry to developing and deploying a web app is now so low that I can see people building their own personal web services for things like their desktop and mobile phones. You now control your personal information and can use open standards for sharing that information.

Posted on April 9th, 2008 | Filed under android, mobile | No Comments »

OpenID is an open standard for decentralized authentication. The OpenID site has plenty of detailed documentation about the protocol so I will briefly explain the basics needed to understand how to integrate OpenID authentication into your grails project.

OpenID Provider
A user registers an OpenID through an OpenID provider. This is the site that provides the identifying URL for the user and handles the authentication request from the Relying Party.

There are a number of OpenID providers out there, with new ones cropping up all the time. I use myopenid simply because it was one of the first openid providers I had heard of. Many sites also provide an OpenID when you sign up for their service. This has lead to OpenID providers that aggregate all of your other OpenIDs. Since we want to drive adoption and there are probably more providers than consumers at this point, we are going to focus on just being an OpenID relying party.

Relying Party
The relying party is the web service that uses OpenID to handle it’s authentication. It prompts the user for their OpenID URL and redirects the user’s browser to the Provider’s authentication page, the provider prompts the user with information about the site making the authentication request, allows the user to accept or reject authentication with the site and then redirects the user back to the relying party with an authentication token that the relying party then verifies. The user never enters a password with the relying party, the provider can also allow automatic authentication with the relying party if they so choose.

Discovery
You can use any web address as your OpenID simply by including the following html in the head tag of your site.


<link rel="openid.server" href="http://youropenidserverendpoint">
<link rel="openid.delegate" href="http://youropenid/url">

This lets you use your blog and any other site you may have as your OpenID. The relying party will parse this information from whatever URL you pass to it.

Setup
I am using code and comments taken from the OpenID4Java getting started page and adapting it for quick integration with grails. If you need anymore detail than I have provided you should check out their wiki. The full source code for our example can be found here: UserController.groovy

1. Sign up for an OpenID, we want one to ease testing obviously.

2. Download the excellent OpenID java library OpenID4java and put the jar and its dependencies in your lib directory. Watch out for dependency versioning conflicts since grails uses many of the same dependencies.

3. For our example we will use a User controller, so go ahead and create a user controller. I won’t really go into modelling a User domain class but with OpenID you can skip all of the password management and storage and simply have a field for their OpenID URL instead.

Getting Started

We need to specify a return URL that the provider will redirect to after authentication is finished. You can store this in a number of places but I will just put it in the UserController. This URL corresponds to the auth action will will implement in UserController.


String _returnURL = "http://localhost:8080/openidtest/user/auth";

The controller actions share a ConsumerManager that is used to perform various steps of the OpenID authentication, I made it a static variable in the UserController because it seems to not work otherwise, there is probably a better way to do this.


  static ConsumerManager manager = new ConsumerManager();

Actions
We will define a few actions on our controller, these will be used to initiate and verify the OpenID authentication process.

login
The first action is login, this action simply presents the user with an OpenID entry field.


def login = {

    		if(session.user){
    			redirect(action: 'index') //redirect to main user page
    		}
    }

If the user is already logged in we redirect.

Here is gsp code for including an OpenID login field for your app, include it in your login.gsp view. Don’t forget to save the OpenID icon to your images directory.


<img src="${createLinkTo(dir:'images',file:'icon_openid.gif')}" alt="openid_logo" />
<g:form name="loginForm" action="handleLogin"><g:textField name="openid" value="http://yourname.myopenid.com" />
<g:actionSubmit value="Login" action="handleLogin" />
</g:form>

handleLogin
This action will take the user’s OpenID URL, create an authentication request and redirect the user to their OpenID Provider.


def handleLogin = {

    try{
		// disable realm verification
    		 RealmVerifier rv = new RealmVerifier();
    		 rv.setEnforceRpId(false);
    		 manager.setRealmVerifier(rv)

    		 // perform discovery on the user-supplied identifier
    		    List discoveries = manager.discover(params['openid']);
    		    DiscoveryInformation discovered = manager.associate(discoveries);

    		    // store the discovery information in the user's session for later use
    		    session.discovered = discovered

    		    // obtain a AuthRequest message to be sent to the OpenID provider
    		    AuthRequest authReq = manager.authenticate(discovered, _returnURL);

    		    response.sendRedirect authReq.getDestinationUrl(true)
    		    }catch(DiscoveryException e){
    		    	//add flash message , failed to find openid at address
    		    	flash.message = "Failed to find valid openid URI at specified address"
    		    	redirect(action:'login')
    		    }
    }

auth
The auth action is the action specified by our service that the OpenID provider will redirect the user to after authenticating with the provider. The provider includes a number of parameters so that the relying party can verify that the user has actually authenticated with the provider.


 def auth = {

    	    // check if this is an openid message, this is to avoid someone
	    // calling the auth action themselves
    	    if(!params['openid.mode']){
    	    	redirect(action:'err')
    	    return;
    	    }

    	    ParameterList openidResp = new ParameterList(request.getParameterMap());

    	    // retrieve the previously stored discovery information
    	    DiscoveryInformation discovered = (DiscoveryInformation) session.discovered;

    	    // extract the receiving URL from the HTTP request
	    // is there an easier way to get the full path including servername and port?
    	    StringBuffer receivingURL = new StringBuffer('http://' + request.getServerName() + ':' +
  request.getServerPort() +request.forwardURI);
    	    String queryString = request.getQueryString();
    	    if (queryString != null && queryString.length() != 0)
    	        receivingURL.append('?').append(request.getQueryString());

    	    // verify the response
    	    VerificationResult verification = manager.verify(receivingURL.toString(), openidResp, discovered);

    	    // examine the verification result and extract the verified identifier
    	    Identifier verified = verification.getVerifiedId();

    	    if (verified != null){
    	    	//User.findByUrl(verfied.getIdentifier())
    	    	session.user = verified
    	    	 // success, use the verified identifier to identify the user
    	    	redirect(action: 'index')

    	    }else{
    	        // OpenID authentication failed
    	        redirect(action: 'err')
    	    }

    }

request.forwardURI is a grails specific method that actually calls request.request.requestURI, this is needed to verify the previously called URL that made the authentication call to the provider.

err
The err action is the action we will redirect to if our authentication fails at any point. You can probably get away with just redirecting the the grails default error page.

Filter
Our final step is to set up an Authentication filter like the one we made for basic authentication . The only difference is that we have a number of controller actions that we want to allow to pass the filter, like login, handleLogin, auth, and err.


class SecurityFilters {
	class SecurityFilters {
	def filters = {
			loginCheck(controller:'*', action:'*') {
		           before = {
		        		   log.trace("inside of filter")
		              if(!session.user && !actionName.equals('login') &amp;amp;&amp;amp; !actionName.equals('handleLogin') && !actionName.equals('auth') && !actionName.equals('err')) {
		                  redirect(controller:'user' , action:'login')
		                  return false
		               }
		           }

		}
	}
}

OpenID, Authorization, and APIs
Since OpenID focuses on authentication there is not currently a good way to incorporate OpenID with API calls. Having to redirect a user to a web page is not something someone programming a mobile or desktop application wants to do in order to make API calls. There have been rumblings of integrating an API http header authorization mechanism into the OpenID standard, and of course you could always integrate OAuth and OpenID so the user would only have to do web based authorization once for your application.

Posted on March 20th, 2008 | Filed under grails, identity, java | No Comments »