cancan skip_authorization_check for Devise authentication
Asked Answered
T

1

20

Because anyone can sign up and then log in,... and because a user isn't identified for roles until after log in, doesn't it make sense to skip authorization_check for Devise?

Going on that premise, i inherit from the Devise registration controller with this registrations_controller and placed it in the controller directory.

class Users::RegistrationsController < Devise::RegistrationsController
  skip_authorization_check
end

change to the routes file:

devise_for :users, :controllers => { :registrations => "registrations" }

I'm missing something though:

This action failed the check_authorization because it does not authorize_resource. Add skip_authorization_check to bypass this check.

Thanks for your help.

Tunisia answered 11/8, 2011 at 1:24 Comment(2)
@RyanBigg, when i get past this issue, i'm going to see if your answer to the prior question is the correct one for the app. Thanks.Tunisia
@Hosemeyer, I need to get past this issue before i can follow your advice in the other question. Thanks for your help.Tunisia
G
42

The easy solution

check_authorization :unless => :devise_controller?

If you have to put check_authorization in every controller manually at some point you will forget and open a security hole in your app. It's better to explicitly whitelist controllers that don't need auth by cancan.

This is made clear in the CANCAN docs at

https://github.com/ryanb/cancan/wiki/Ensure-Authorization

EDIT

class ApplicationController < ActionController::Base
  check_authorization :unless => :do_not_check_authorization?
  private
  def do_not_check_authorization?
    respond_to?(:devise_controller?) or
    condition_one? or
    condition_two?
  end

  def condition_one?
   ...
  end

  def condition_two?
   ...
  end
end
Girt answered 14/2, 2012 at 13:20 Comment(9)
Thanks bradgonesurfing +1. When I come back to revise and test this code, I'll change accepted answer if it all works out your way.Tunisia
The answer is still with Mr Bigg which is scored at (-1)Girt
Problem I am having is that, in addition to the devise controller, there are two other controllers I would like to skip. I have been unable to modify the 'unless' condition to add those. I could put 'skip_authorization_check' in those, but it would be better if there were only one location in the app that handled all exceptions.Tunisia
It's easy and outlined in the docs as well. I've updated the answer with an example of creating a more complex condition.Girt
For others reading this I'd suggest not using or in your boolean checks you should really be using ||. Otherwise, great answer.Colvin
just wanted to point out that :do_not_check_authorization? should return false in order to skip authorization. if you use :if => ... instead then this will expect true to skip.Hawkeyed
@Colvin Why shouldn't we use or?Windstorm
@Windstorm It used to be the case that they behaved differently. It looks like Ruby 2.0 may have changed that, but old habits die hard. estebanpastorino.com/2013/09/12/…Colvin
For anyone using customised devise controllers, I think it works the same for those too. I added what I know here https://mcmap.net/q/662588/-check_authorization-causes-custom-devise-controller-to-failShari

© 2022 - 2024 — McMap. All rights reserved.