A Review of Authentication and Access Control for Ruby On Rails

A review of Authentication and Access Control for Ruby On Rails

Previous Articles That Are Related
http://mentalpagingspace.blogspot.com/2007/11/getting-started-faster-in-...
http://mentalpagingspace.blogspot.com/2008/12/rails-to-windows-integrati...

First, to give some context, when building Rails apps, its common practice to use
a common set of plugins. In "EDGE" rails, there is even a template system so that
when you create a rails apps, it can load your standard plugins.

For my basic set, I use the following:

My base set is:
ActsAsAuthenticated (Login)
http://www.railslodge.com/plugins/1-acts-as-authenticated
RestfulAuthentication (The Replacement for the above)
http://github.com/technoweenie/restful-authentication/tree/master
RoleRequirement (Access Control in controllers and menus)
http://code.google.com/p/rolerequirement/
Tabnav/Widgets (Menus)
http://wiki.github.com/paolodona/rails-widgets
ActiveScaffold (Controller/View for CRUD)
http://activescaffold.com/

In rails there are "two" different problems, first there is authentication, then there is access control.

Authentication is:
1. How do we login to the app
2. User Model
a. User Name
b. Email Address
3. What Access do we have? (Roles)

Do do the heavy lifting for this, we use a plugin

There are several different plugs for authentication:
1. ActsAsAuthenticated (The original)
3. RestfulAuthentication (The new "standard")
2. OpenId
3. NTLM (Use this when your app is only in a ActiveDirectory environment)

So once your logged in, using one of the above, we ad the rolerequirement plugin.

I find RoleRequirement handles my access control very nicely. It enhances your user model, with the ability to have
multiple role. You can then use the "role" to verify in your menus and controllers if a user can perform or use
certain actions.

If you look at rolerequirement, in your code, you can do something like the following:

class Adminspace::AdminController < ApplicationController
before_filter :login_required
require_role "admin"

layout 'basic'
def index
end
end

Notice the require_role above.
When you setup rolerequirement, You can login to your app, and add additional roles.
You can also add a migration to add these roles. (Useful in a empty database setting.

Also notice the before filter. This makes sure the user is logged in.

The next issue you will get is, updating menus on the fly.
I use tabnav typically for my menus.

So in order to make menus come and go based on roles, you can check roles in tabnav.

<%
# this partial renders a tabnav
render_tabnav :aircenter,
:generate_css => true do

add_tab do |t|
t.named 'ReqCenter'
t.titled 'ReqCenter'
t.links_to :controller => '/reqcenter'
end
if @current_user.has_role?('admin')
add_tab do |t|
t.named 'Admin'
t.titled 'admin'
t.links_to :controller => 'adminspace/admin'
end
end
add_tab do |t|
t.named 'Requests'
t.titled 'Requests'
t.links_to :controller => 'requestspace/requesthome'
end
add_tab do |t|
t.named 'Logout'
t.titled 'Logout'
t.links_to :controller => 'adminspace/account', :action => 'logout'
end
end
%>

A example of a Admin CRUD, using ActiveScaffold:

class Adminspace::UserController < ApplicationController
layout 'tier1admin'
before_filter :login_required
require_role "admin"

active_scaffold :users do |config|
config.list.columns = [:id,:display_name,:businessunit,:department,:location]
config.columns[:businessunit].ui_type = :select
config.columns[:location].ui_type = :select
config.columns[:department].ui_type = :select
config.columns[:roles].ui_type = :select
end
end

So now, using namespaces, we can have a admin controller, with a role of admin for access, that allows the admin
to change anything in all users, and another controller, that allows only the user to change his own fields.