heartcombo / devise

Flexible authentication solution for Rails with Warden.
http://blog.plataformatec.com.br/tag/devise/
MIT License
23.98k stars 5.55k forks source link

before_action :authenticate_user! not working #3349

Closed stevejc closed 9 years ago

stevejc commented 9 years ago

I am unable to get before_action :authenticate_user! to work in my controllers which inherit from Devise.

class RegistrationsController < Devise::RegistrationsController
  before_action :authenticate_user!
  def hello_world
    redirect_to pricing_path
  end
end

before_action :authenticate_user! works as expected in the other controllers.

josevalim commented 9 years ago

You need to give us more information on how to reproduce this issue, otherwise there is nothing we can do. Please read CONTRIBUTING.md file for more information about creating bug reports. Thanks!

rubyrider commented 9 years ago

@stevejc show your model, route and application controller!

stevejc commented 9 years ago

I believe my problem was I didn't include @request.env["devise.mapping"] = Devise.mappings[:user] in my spec. I didn't realize it applied to controllers that inherit from devise.

josevalim commented 9 years ago

It only applies to devise controllers. :)

José Valimwww.plataformatec.com.br http://www.plataformatec.com.br/Founder and Lead Developer

MarkMurphy commented 9 years ago

I'm having a similar issue. I have a controller that looks like this:

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :authenticate_user!

  def upgrade
    ...
  end
end

and a route which looks like this:

devise_for :users, skip: [ :sessions, :registrations, :passwords ]

devise_scope :user do

  ...

  get     "upgrade", to: "users/registrations#upgrade"

  ...

end

It's almost like it's ignoring the before action. I think is has something to do with this line https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/helpers.rb#L112

I think it's skipping authenticating because it thinks this controller is a devise controller?

josevalim commented 9 years ago

Mark, why don't you use your own controller for this? Why are you inheriting from the Devise one? It just brings complexity and your code seems to be just fine to have in a UpgradeController.

José Valimwww.plataformatec.com.br http://www.plataformatec.com.br/Founder and Lead Developer

MarkMurphy commented 9 years ago

@josevalim I'm also overriding the new and create actions. Didn't really want to copy the entire registration controller which is why I'm inheriting from it instead.

josevalim commented 9 years ago

It is not about copying its contents. Override new and create in the registrations controller, move the upgrade action to its own controller.

jmuheim commented 9 years ago

It only applies to devise controllers. :)

@josevalim, can you explain why?

I'd like to extend my RegistrationsController from Devise::RegistrationsController so I can just add to the existing files and folders (e.g. app/views/devise/registrations/show.html or spec/features/user/registration/show_spec.rb). But as written above, before_filter :authenticate_user! won't have any effect this way.

Update

As I am also using CanCanCan, I'm solving the problem like this at the moment:

class RegistrationsController < Devise::RegistrationsController
  # before_filter :authenticate_user! # Doesn't seem to work, see https://github.com/plataformatec/devise/issues/3349#issuecomment-88604326
  before_filter :load_and_authorize_current_user
  respond_to :html

  # We can't rely on CanCanCan, as it relies on a params[:id] which isn't present, and by manually setting @user, the authorization isn't performed anymore. See https://github.com/ryanb/cancan/issues/452#issuecomment-88614091.
  def load_and_authorize_current_user
    @user = current_user
    authorize!(params[:action].to_sym, @user)
  end
end
ce07c3 commented 6 years ago

Ran into the same issue. It's not obvious why the user does not get authenticated. Overriding a !-method to not raise an exception is a big surprise.

jmuheim commented 6 years ago

Still a problem on my side. Didn't find a way to make authentication enforcement work.

alexisraca commented 6 years ago

I'm overriding an action in a devise controller and adding an after_action, it is also ignoring the after_action. Is there a reason for this behaviour?

brycedarling commented 6 years ago

@ce07c3 @jmuheim @alexisraca I ran in to this today as well. The following worked for me (the trick is force: true):

class RegistrationsController < Devise::RegistrationsController
  before_action ->{ authenticate_user!(force: true) }

  ...
end
mbaev commented 5 years ago

I found one more solution which is worked for me:

class RegistrationsController < Devise::RegistrationsController
  prepend_before_action :authenticate_scope!

  ...
end
alexisraca commented 5 years ago

https://github.com/plataformatec/devise/blob/e3a00b27d19ba995891d7dd92394fe2900a789c2/app/controllers/devise/registrations_controller.rb#L130-L134

This seems to be conflicting the customization of the controller. I haven't tried to debug it but an override could fix this instead of layering forced before_actions because we could be triggering multiple undesired authenticate_resource calls

ApoorvChandurkar commented 3 years ago

I found one more solution which is worked for me:

class RegistrationsController < Devise::RegistrationsController
  prepend_before_action :authenticate_scope!

  ...
end

This Worked like a charm for me!

chamox commented 1 year ago

I found one more solution which is worked for me:

class RegistrationsController < Devise::RegistrationsController
  prepend_before_action :authenticate_scope!

  ...
end

Worked for me! thank you :heart: