RESTful Rails and Mobile Devices

March 13, 2010 by · 7 Comments 

My partner, Karen, has done a remarkable job at creating the web application for our first property. Sadly, I’m responsible for implementing an Android application which invokes it’s powerful magic. Life is good when one stays within the Rails web application, but RESTful interfaces are meant to make exchange of data from machine to machine easy and well defined. If only life were so simple…

Rails implements protection against Cross-Site Request Forgery (CSRF) protection.  If you have a look at a form created with Rails, you’ll notice a hidden field for an authenticity_token.  This is a hidden field with a randomly generated token to ensure that inauthentic clients can’t muck with your data.

In our application, the login form has the following hidden field lurking:

<input name="authenticity_token" type="hidden" value="XRGy4w54tVmDtzwkLK/DfDIfWcIHf9h8nnwcefpBCeE=" />

This lovely thing is an important mechanism to protect the site from CSRF exploits.  If a client does not have the appropriate authentication key, any attempt to POST, DELETE, or PUT will be rejected.  This feature can be easily disabled by simply going to the application directory’s config/environment/ directory and adding the following for test, development or production as necessary:

# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection    = false

As a default, this is only a default for “test.rb” and none of the others, however while tinkering around with an application on your PC you are most likely invoking the development.rb options.  With this option disabled, one can simply us an HTTP post to the URL corresponding to the resource in question as follows.  For example, a user model with a login, email and password can be created as follows using cURL:

curl -d "user[login]=Kiwi" -d "user[email]=kiwi@kiwiluv.com] -d user[password]=wishicouldfly" http://localhost:3000/users

With CSRF protection disabled, this will work fine.  Unfortunately the site will have a vulnerability.  With it enabled, Rails will cheerfully tell you to pound sand.

Obviously the CSRF implementation is a valuable tool, but one that forces us to think a bit more about the proper mechanism for non-browser clients to access the resources on the site.  Sorry to say I haven’t quite figured this one out to my satisfaction, but when I do so I’ll certainly share.

I have a  few ideas, so stay tuned…

About dave@kiwiluv.com

Comments

7 Responses to “RESTful Rails and Mobile Devices”
  1. Alan says:

    hey dave, came across your post when searching for information about this specific topic. I’m dabbling around in with the iPhone SDK and am spinning my wheels trying to figure out how to http post to rails with CSRF enabled. Have you made much headway?

  2. Unfortunately not. At the moment, I am either a) avoiding the problem by not protecting interfaces not capable of altering server data or b) creating a completely unique controller for posting from mobile devices which does not use the scaffolding which implements CSRF. If you’re using web forms, you want to have this. But there’s nothing forcing you to do so aside from “that’s the way the web has always worked” thinking. What I’m considering is a session cookie or some such thing where when a mobile device opens an HTTP session, following authentication a session hash must be exchanged. This is basically the same method that CSRF uses to ensure that the Rails app is using the correct token.

    I suppose that it might also be possible to have your mobile application scrape the CSRF token from the rendered web form and use it for posts within the same session. Not sure if that would work not knowing the underlying Rails implementation. That’s the beauty and danger in Rails…it’s easy to get stuff up, but it’s hard to know what’s going on behind the curtain.

    I’ll need to deal with this in our application soon, so rest assured when I figure out a solid approach I’ll share it!

  3. Alan,

    Just noticed that Josh Owens is giving a talk at the upcoming RailsConf on building an API with rails. That’s local to me but I’m not sure I can make it. In any case, if you can it may help. Also, his blog has some commentary on it, although not too technical. He seems to be active in that space so you may want to keep an eye on his work.

    http://en.oreilly.com/rails2010/public/schedule/detail/14502
    http://railsfreak.com/

  4. Jason says:

    Hi Dave,

    I’m wondering if you ever came put with a good solution for this, as I’m currently wrestling with the same problem.

    Cheers,
    Jason

  5. I have to revisit this problem again, this time with an image upload involved. I’ll post that journey of discovery here. This time, I am doing it from a Phonegap iPhone/Android app so the actual code will be Javascript on the client side. If the image weren’t involve, I probably would push it directly into the MongoDB database.

    I haven’t thought through all the details yet but will certainly share how I end up doing it.

  6. gogu says:

    Hi Dave,
    Do you have a solution for the problem. Could you please share it with us if you have.

    Thanks

  7. @cyri_ says:

    The solution is to use a static & unique auth_token param by authenticable user in request HEADER.

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!