If you thought you had a lot of options as a Rails developer for adding authentication to your Rails applications, search GitHub or RubyGems.org sometime for role or authorization. As you’ll see, the need to add an authorization layer to applications is a common one with more than one solution. In this post I won’t talk much code, nor will I give you a list of gems—that’s easy enough to create for yourself. Instead, I will talk about the thought processes I go through when adding an authorization layer to a new project.
Why is authorization important? Rather than try to answer this question myself, let me remind you of last summer’s breach at Citi, when hackers stole more than 200,000 credit card numbers. The approach? Logging in, then changing the account number in the URL. Want to bet some developers lost their jobs over that one?
Before you invest a lot of time adding a complex authorization layer to your app, assess what’s necessary. How many different types of users will you have? What will those users be able to do (or not do)? A lot of times you or your customer may start a project assuming that you’ll need complex roles, when in reality you’ll only need a handful—and in some cases, a full-blown authorization layer isn’t required for the level of security you need:
current_user.admin?(note: I prefer to use
current_user.is_admin?, only because I like the way it reads). That said, if you feel the urge to just add a boolean for each role a user might have (
is_editor?, etc.), stop yourself immediately and plan to integrate a more robust roles solution.
It’s relatively easy to migrate from either of these scenarios to a more complex one if and when the time comes. In the short term, however, they may provide all the security you need to ship your initial project.
Assuming you’ve walked through the thinking processes I’ve outlined above, and you’ve determined that your current authorization needs are more complex than a simple boolean can handle, then it’s time to peruse GitHub and/or RubyGems.org for a good roles manager. You can also create your own—this is the approach I’ve taken after experimentation with several gems. Making your own roles solution isn’t difficult; this Railscast on embedded associations shows one way to accomplish it. Whether you opt for someone else’s gem or your own code, though, consider these questions:
destroyfunctionality in controllers to add the blocked role, versus actually deleting a user or membership).
At this point I’m ready to actually build the authorization layer. If it’s anything more complex than a couple of calls to
current_user.is_admin? I almost always use CanCan. It’s flexible, up-to-date, and thoroughly documented. In the past I used RESTful_ACL, which took a different approach to authorization but got the job done. I featured RESTful_ACL early on in Everyday Rails; consult the archives to learn more.
Finally, if you’re not writing tests for your Rails apps, then building an authorization layer may make you want to finally start. Otherwise you’re looking at some incredibly tedious in-browser testing. No thanks. Most authorization systems you’ll find on GitHub should include instructions on how to test them. In the case of CanCan I test the actual Ability model; I also test to make sure things are working as they should in either a request or controller spec.
That, in a nutshell, is the process I take when adding authorization to an application. While the tools will change over time, I hope this provides a good roadmap for your own work.
If you liked my series on practical advice for adding reliable tests to your Rails apps, check out the expanded ebook version. Lots of additional, exclusive content and a complete sample Rails application.
Ruby on Rails news and tips, and other ideas and surprises from Aaron at Everyday Rails. Delivered to your inbox on no particular set schedule.