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.

Jay
  • 6,206
  • 11
  • 48
  • 82
  • @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. – Jay Aug 11 '11 at 01:33
  • @Hosemeyer, I need to get past this issue before i can follow your advice in the other question. Thanks for your help. – Jay Aug 11 '11 at 02:00

1 Answers1

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
bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217
  • 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. – Jay Feb 14 '12 at 20:41
  • The answer is still with Mr Bigg which is scored at (-1) – bradgonesurfing May 27 '12 at 20:46
  • 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. – Jay May 28 '12 at 13:38
  • It's easy and outlined in the docs as well. I've updated the answer with an example of creating a more complex condition. – bradgonesurfing May 28 '12 at 17:46
  • For others reading this I'd suggest _not_ using `or` in your boolean checks you should really be using `||`. Otherwise, great answer. – RyanJM Jun 09 '13 at 21:21
  • 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. – FireDragon Jan 15 '14 at 08:40
  • @RyanJM Why shouldn't we use `or`? – Andreas Jun 15 '16 at 08:03
  • 1
    @Andreas 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. http://estebanpastorino.com/2013/09/12/quick-ruby-tip-double-pipe-vs-or/ – RyanJM Jun 15 '16 at 16:29
  • For anyone using customised devise controllers, I think it works the same for those too. I added what I know here https://stackoverflow.com/a/64520714/5783745 – stevec Oct 25 '20 at 05:46