Monday, August 23, 2010

Authenticating Android to App Engine using the phone's credentials

If this helps you, please consider visiting the adds on this blog which supports the time i'm spending putting this stuff together. I'd also be very happy to see you follow this blog.

User this code at your own risk, it is provided as is with no warranty.

With the latest release of my Free and Social Data Logger App for Android (learn more about that on www.nimbits.com)  I took advantage of Android 2.2 account sync features. My app uses Google App Engine for a back end service and Restlet (www.reslet.org) to provide web services hosted on app engine. On Android we need to make requests to App engine with the users Google account attached to the request so App Engine knows who they are.

Actually, the Nimbits Android App is Open Source - as are all of the interfaces to Nimbits Data Logger - all of the code for the Android App is here: https://code.google.com/p/nimbits/

Don't forget to add Google credentials to the emulator if you're using one to debug your code.

Permissions:

In your Android Manifest, you'll want to add

  • GET_ACCOUNTS
  • USE_CREDENTIALS
  • READ_OWNER_DATA 


Authentication Code

I'm sorry if my code isn't as clean and re-factored as I normally like it (maybe if things stop changing every week i'll be able to clean thing up)  If you add this code to your app, you'll want to go through and remove any of the refrences to my app: Nimbits and replace them with your apps name and url.

The class for authenticating to Google is GoogleAuthentication.java and it can be downloaded from our source repository.

The  most important part of that class is the getToken() function that is actually asking the phone for the google account.

 AccountManager mgr = AccountManager.get(context); 
Account[] accts = mgr.getAccountsByType("com.google"); 
 Account acct = accts[0];
AccountManagerFuture accountManagerFuture = mgr.getAuthToken(acct, "ah", null, (Activity) context, null, null);


This class will get an oauth token from your app. You can read more about that here:
http://code.google.com/appengine/docs/java/oauth/overview.html

Making the Web Service Call

I put all of my actual web service calls in once class (it's a small app) called DataClient.Java 

This class uses the GoogleAuthentication Class to get a token, and do GETs and POSTs to restlet services on my app engine site.


Let's walk through one of the functions:




public static Double getCurrentValue(String pointName) throws IOException
{
Double retVal;
  //1: Init the Singleton Authentication class
GoogleAuthentication G;
G = GoogleAuthentication.getGoogleAuthentication();
  //2: build the request URL - this is a restlet servlet on my app engine app
URL url = new URL("http://app.nimbits.com/nimbits/Service/value?pointname=" +       URLEncoder.encode(pointName,"UTF-8"));
 //3: Add the auth cookie the authentication class constructed.
URLConnection conn = url.openConnection ();
conn.addRequestProperty("Cookie",G.getAuthCookie().getName() + "=" + G.getAuthCookie().getValue());
  //4: post the request and download the result, in my case the current value of a data point
conn.setDoOutput(true);
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
String result ="";


while ((line = rd.readLine()) != null) {
result +=line;
}
rd.close();
retVal = Double.valueOf(result);


return retVal;


}




So, an android app with the correct permissions should be able to create an instance of the GoogleAuth class, which will provoke the phone into prompting its owner to grant your app permission to use their google credentials, and then make authenticated requests to app engine as if they were logged into it. All without making the user re-enter their password.

No comments:

Post a Comment