29
Comparison of Different Access Controls in Rails By Rashmi Nair

Comparison of different access controls

Embed Size (px)

DESCRIPTION

Comparison of different access controls - Role Based Authorization.

Citation preview

Page 1: Comparison of different access controls

Comparison of Different Access Controls in Rails

By Rashmi Nair

Page 2: Comparison of different access controls

About Me

I am Team Lead at Icicle Technologies.

I am working in ROR for past 5 years.

On twitter you can find me - @rashmignair

Page 3: Comparison of different access controls

Authentication

❏ Allowing users to sign in and identify themselves is called authentication(Identifies a user)

eg: same as you need to swap in order to enter your office. ❏ It can be implemented using Devise or Omniauth

❏ It a flexible authentication solution for Rails based on Warden.

❏ Its encrypts and stores a password in the database to validate the authenticity of a user while signing in.

Page 4: Comparison of different access controls

Authorization

❏ Controls what a user is allowed to do.

❏ Once a user logins, need to check what the user is allowed to access and perform.

❏ These checks are on the basis of different roles mentioned in the application and the functions that the role can perform

Page 5: Comparison of different access controls

Role-Based Authorization

❏ Role-based authorization is suitable for simple applications without complex access rules.

❏ A big advantage is easy conceptualization; it is easy to imagine personas, each with different (but uniform) privileges.

Page 6: Comparison of different access controls

Implementing Role-Based Authorization

❏ Implement using CanCan (cancancan)

❏ Implement using Pundit

Page 7: Comparison of different access controls

Implement using CanCan

❏ Simple and powerful

❏ Authorization library for Ruby on Rails

❏ All permissions are defined in a single location (the Ability class)

Page 8: Comparison of different access controls

Implementation

❏ Add gem to your Gemfile and run the bundle command. >> gem "cancan"

❏ Define Abilities

>> rails g cancan:ability

Page 9: Comparison of different access controls

app/models/ability.rb

class Ability include CanCan::Ability

def initialize(user) endend

Page 10: Comparison of different access controls

Advantage

❏ Check Abilities & Authorization

❏ Handle Unauthorized Access

❏ Manage authorization in a single file

Disadvantage

❏ Ability files quickly become too big to manage, and there is no built in strategy for splitting up abilities across multiple files.

Page 11: Comparison of different access controls

Disadvantage

❏ Even worse, there is no natural way to structure ability files. We usually resort to comments to divide the file into sections for different models.

❏ All ability rules need to be evaluated for every request. While not a huge performance hit, it seems like a built in wastefulness.

❏ The test suite depends on ActiveRecord < 3.1

Page 12: Comparison of different access controls

Implement using Pundit

❏ It provides a set of helpers which guide you in leveraging regular Ruby classes and object oriented design patterns.

❏ It helps to build a simple, robust and scalable authorization system.

Page 13: Comparison of different access controls

Installation

❏ gem "pundit"

❏ Add the following in Application controller

class ApplicationController < ActionController::Base

include Pundit

protect_from_forgeryend

Page 14: Comparison of different access controls

❏ rails g pundit:install

❏ It focusses on Policies

❏ Mention the policies to be followed for the model in a class which has the same name as the model followed by policy for eg: TaskPolicy

Page 15: Comparison of different access controls

class TaskPolicy < ApplicationPolicy def initialize(user, task) @user = user @task = task end

def create? user.role?(:project_manager) || user.role?(:team_lead) end

def update? user.role?(:project_manager) || user.role?(:team_lead) || user.id == @task.user_id end

end

Page 16: Comparison of different access controls

class TasksController < ApplicationController

def index @tasks = policy_scope(Task) end

def create @task = Task.new(params[:task]) authorize @task, :create? @task.save redirect_to @task end

def show @task = Task.where(params[:id]) authorize @task, :show? end

end

Page 17: Comparison of different access controls

Implementing Scopes

❏ Define a class called a policy scope

❏ The class has the name Scope and is nested under the Policy class

❏ Instances of this class respond to the method resolve, which should return some kind of result which can be iterated over.

Page 18: Comparison of different access controls

class TaskPolicy < ApplicationPolicy class Scope attr_reader :user, :scope

def initialize(user, scope) @user = user @scope = scope end

def resolve if user.role?(:project_manager) scope.all else scope.where(:published => true) end end end

def update? user.role?(:project_manager) || user.role?(:team_lead) || user.id == scope.user_id endend

Page 19: Comparison of different access controls

Advantage

❏ segregating access rules into a central location.❏ policy objects are lightweight❏ keeps your authorization logic out of controllers and models.

Disadvantage❏ Passing new parameter to the policy_scoped method is difficult

Page 20: Comparison of different access controls

Use Case

❏ Considering an example for a system, with the following roles - Project Manager, Team Lead, Team Members

❏ Rules to be defined are as follows:1. Project Manager can do everything(Creating Milestone, Adding

Tasks, Add Members to Project)2. Team Lead(Add Task, Update Task, Delete Task )3. Members(Can only view all the task, but can update only the task

assigned to them)

Page 21: Comparison of different access controls

Project Manager

class Ability include CanCan::Ability

def initialize(user) # Define abilities for the passed in user here. For example: if user.role?(:project_manager) can :manage, :all else ……. end end end

class TaskPolicy < ApplicationPolicy class Scope end def create? user.role?(:project_manager) end def update? user.role?(:project_manager) endend

Page 22: Comparison of different access controls

Team Lead

class Ability include CanCan::Ability

def initialize(user) # Define abilities for the passed in user here. For example: if user.role?(:project_manager) can :manage, :all else can :read, :all if user.role?(:team_lead) can :update, Task can :delete, Task end end end end

class TaskPolicy < ApplicationPolicy class Scope end def create? user.role?(:project_manager) || user.role?(:team_lead) end def update? user.role?(:project_manager) || user.role?(:team_lead) endend

Page 23: Comparison of different access controls

Team Member

class Ability include CanCan::Ability

def initialize(user) if user.role?(:project_manager) can :manage, :all else can :read, :all can :update, Task do |task| task.try(:user) == user || user.role?(:team_lead) end if user.role?(:team_lead) can :delete, Task end end endend

class TaskPolicy < ApplicationPolicy def initialize(current_user, model) @user = current_user @task = model end def create? user.role?(:project_manager) || user.role?(:team_lead) end def update? user.role?(:project_manager) || user.role?(:team_lead) || @user == @task.user endend

Page 24: Comparison of different access controls

View File (Cancan)

views/tasks/index.html.erb

<% if can? :create, Task -%> <%= link_to 'Add Task', new_task_path -%><% end -%>

<% @task.each do |task| -%> <p> Task Name: <% @task.task_name -%></p> <p><%= link_to 'Show', task_path(@task) %></p>end

Page 25: Comparison of different access controls

<% if policy(@task).show? %> <%= link_to 'Task', task_path(@task) %><% end %>

<% policy_scope(@user.tasks).each do |task| %> <li> <h2><%= task.task_name %></h2> <p><%= link_to "Edit", [:edit, task] if policy(task).edit? %></p> </li><% end %>

View File (Pundit)

Page 26: Comparison of different access controls

Comparison

Cancan

❏ simple approach is to isolate all authorization logic into a single Ability class.

❏ single user role

Pundit

❏ provides a set of helpers to build your own authorization system using plain Ruby classes.

❏ supports complex

application with multiple roles

Page 27: Comparison of different access controls

CanCan Pundit ❏ drawback is that all abilities

for that user’s role needs to be evaluated for each request

❏ Become difficult to use when there are complex roles

❏ No support for Rails 4

❏ only evaluates the ability for the requested resource’s action

❏ can be leveraged in building your own authorization system that meets your project’s needs

❏ Has support for Rails 4

Page 28: Comparison of different access controls

References

http://www.elabs.se/blog/52-simple-authorization-in-ruby-on-rails-apps

https://github.com/elabs/pundit

http://www.distilnetworks.com/cancan-vs-pundit-choose-pundit-authorization/

Page 29: Comparison of different access controls

Thank You