Monday, April 30, 2007

Authentication in Ruby on Rails

I've been getting sporadic time fragments to spend on Ruby on Rails, hardly throwing myself into it, but the best I can manage with my work and family commitments. One of the key items I'm wrestling with is user authentication.

This is an important area to me as any web app I am likely to write in Rails will need to authenticate users, at the very least site admins, but more likely regular users that have private data/functions they need to access.

Allow me to explain a crucial point here; when people look at application security there are two related, but different, concepts that are often confused. These are authentication and authorisation.
Authentication
This is how you prove that you are who you claim to be. An authenticated user is one who we accept the identity of.

Authorisation
This is how we determine what you are allowed to do. The first step is always to authenticate that you are really who you claim to be, the next is to determine what authorisation you have been granted within our application.
I actually intend to implement both concepts in my breakable toy apps, but unless I can find a good answer to the first one, I won't be able to do the second.

Fortunately authentication systems can be easily shared, for example I could try to implement Google account authentication, which would allow users to login to my application using their Google account. The acts_as_google_account plugin might give me exactly what I need in this area. That places the burden of user administration on Google and leaves me just worrying about authorisation.

It is much harder to take on board someone else's authorisation system, as it is by necessity interwoven with the object model we are using, and may not meet anyone else's expectations about how to control user access. A truly orthogonal authorisation system may be possible, but I have yet to see one.

Anyway, my problem at the moment is that acts_as_google_account has minimal documentation, no test cases and a module called "Foo" ... hardly something that instils confidence in the code. I could look at the Acts as Authenticated plugin, which at least is documented (almost well documented) and widely used, and someone has already worked out how to install the plugins as generators (which is more what they are).

ModelSecurity is very nice as it implements at the model level, avoiding the potential loopholes that controller-based authorisation schemes provide (e.g. a new controller is built that exposes the models without implementing the right security scheme). However there are some concerns with its integration with auto-completing text fields. But at least some of the issues have been worked out for me.

I had read someone complain that ModelSecurity implements a single level of security, which would be less than useful for me, however a read of the ModelSecurity class reference shows that the security scheme allows you to specify any test you like, so you could implement user security groups or other funkiness as you will (e.g. allow access for users whose firstname begins with "A" and a date of birth in April for any even-numbered year).

Other possibilities are to look at ActiveRBAC (RBAC = Role-Based Access Control) and the Authorization plugin.

Of them all, ModelSecurity appeals to me the most as it secures at the lowest level possible. Hopefully the next time I write about this I will have implemented it in one of my toy apps.

2 comments:

  1. hi
    i have developed one rails application and i want to login into that application with google id and password.

    please suggest me on this issue(provide code)

    ReplyDelete
  2. Ravi,

    Sorry I don't have the time to create the sourcecode for you, but I recommend you check out the QuarkRuby Ruby on Rails Security Guide.

    However, they will also point you at the same acts_as_google_account plugin that I mentioned above. Have a look at the sourcecode for that and you should find something you can re-use for your project.

    Regards,
    Angus

    ReplyDelete