I recently started playing with the JREngage plugin for Android. I have been a long time user of Janrain’s multi-host OpenID authentication services, and was interested to see how easily I could build a login system within my Android application. It was trivial to get this working. And, as a bonus, you can then have your Android application seamlessly talk to your webapp (provided authentication into it is also via Janrain). There was one implementation issue which stumped me for a day related to the way Rails handles authentication (specifically how and when it decodes session cookies to prevent against CSRF attacks), so I thought I would document that here.

First, if you follow the instructions here on the Janrain documentation, you can quickly get an Android application running using the JREngage libraries.

It was not immediately obvious to me that there are two steps when you use JREngage to authenticate an Android application. The first is when your Android application logs in using any of the OpenID providers supported by Janrain. Once this is completed, you will be returned to the callback jrAuthenticationDidSucceedForUser in which you can then extract information from the authInfo dictionary. For example, once control is returned to my application, I used this bit of code to extract the email address which I then display in my Android application:

The second step is that the Janrain library hits your webservice, which if it is also using Janrain, will authenticate, and then return the session to you, and you can then reuse this session cookie to make requests into your web application as if your Android application was authenticated into your web app via a regular web request (which is what the Janrain library is doing for you under the hood, actually). To use this, specify the tokenUrl of your web application (which is the same URL you specify inside your web-app for the Janrain Javascript API to return to once authentication has completed). And, then if all is setup, you will receive a callback into your Android app (jrAuthenticationDidReachTokenUrl) after this step has completed with a session cookie that you can use inside of your Android application to make requests over an authenticated channel into your web application.

Here is the code I used. First, I liked the Java REST client provided for on Lukencode’s blog. After adding this to my project, I then instantiate a REST object, and then use the session cookie to get inside my application. I banged my head against this for a while, because it did not work originally. I put a debugger statement inside my application_controller.rb to see whether it was pulling the session back from the request coming from Android, and initially it was not. I sniffed out the HTTP header traffic using wireshark to make sure the cookie was being sent in the request header and it was. I inspected the session cookie from the Rails request object and decoded it by hand, and it looked fine, but for some reason when it reached my application controller authentication method the session did not exist. I then noticed the CSRF cookie which was not being sent on the Android request. And, then I realized I needed to ignore this check. If you place the code at the top of your controller to ignore the authenticity token, your webapp will properly retrieve and use the session cookie.