Using Devise before_action :authenticate_user! doesn't do anything - ruby-on-rails

I am trying to require login on all pages on my Rails 4 web site.
In the ApplicationController I have added before_action :authenticate_user!, but it simply doesn't do anything. I have tried to add the same before_action :authenticate_user! to another controller, and it works fine.
Do I need to do something else to the ApplicationController, to make the login be required on all actions (Except signup/signin)?

Here's the actual code we use:
#app/controllers/application_controller.rb
Class ApplicationController < ActionController::Base
#Actions
before_action :authenticate_user! #-> routes to the login / signup if not authenticated
end
The problem you probably have is two-fold:
--
Make sure your other controllers are inheriting from application_controller:
#app/controllers/other_controller.rb
Class OtherController < ApplicationController
...
end
--
You're somehow "skipping" the before_action callback
If you're using skip_before_action anywhere, you need to remove it. It will likely cause a problem with your authenticate_user! method. To fix this, I would firstly test without any skip_before_action callbacks, and then see what gets it working correctly
A further note - signin / signup won't matter. They all inherit from the Devise controllers; they'll just run as required.

UPDATED 2019
In your routes.rb file you may have mentioned only authenticated_user path like below
authenticated :user do
root to: 'home#index', as: :root_app
end
You should mention unauthenticated_user path too to make it work or just root path without unauthenticated_user or authenticated_user

Related

authenticate_user! for all but a single page -- how to do that easily?

I want to use authenticate_user! in all, but a single page "login" page, in my Rails application. For this I can insert authenticate_user! in all the controllers. But it'd be easier to insert it into ApplicationController and
disabe only on "login" page or rather in SessionController for "login" action. Is it possible?
Yes, you can do.,
class ApplicationController
before_filter :authenticate_user!
end
class SessionsController < ApplicationController
skip_before_filter :authenticate_user!
end
And you can mention the methods you want to exclude using except:.

skip_before_action for a few controllers in Rails?

Hi I'm building an api section for an app. My all api related controllers resides inside app/controllers/api directory.
My concern is that in application_controller there is a filter before_action
:authenticate_user!, so I have to be in login mode to access the api.
My current solution: I'm adding skip_before_action :authenticate_user! in all the controllers which are in
app/controllers/api directory..
Problem: I have to write in all the controllers and I have around 80 controllers
My expectation: Is there a way where I can write in application_controller itself something like this
before_action :authenticate_user!, except: [all the controllers which are in api directory]
You will have to specify skip_before_action :authenticate_user! in every controller whose actions aren't supposed to be authenticated. You can not pass the name of controller or any thing like that as an argument to skip_before_action method.
One solution is: You can make a controller called APIController, and you can specify the skip_before_action thing there like:
class APIController < ApplicationController
skip_before_action :authenticate_user!
# rest of the code
end
And then all the controllers at app/controllers/api/ can inherit from APIController.
class OtherController < APIController
end
You can try like this if all the controllers are under API folder:
class ApplicationController < ActionController::Base
before_action :authenticate!
def authenticate!
if params[:controller].split("/").first == "api"
return true # or put code for what wherever authenticate you use for api
else
authenticate_user!
end
end
end

Why flash message won't appear if I use CanCan with Devise?

Assuming that I'm not signed in.
In this case, it displays this flash notice when accessing to actions in mails_controller.
You need to sign in or sign up before continuing.
However, it won't display in communities_controller.
Why? and How can I fix?
mails_controller.rb
class MailsController < ApplicationController
before_filter :authenticate_user!
....
end
communities_controller.rb
class CommunitiesController < ApplicationController
load_and_authorize_resource :find_by => :id
before_filter :authenticate_user!
end
try moving the load_and_authorize_resource line after the before_filter. The load_and_authorize_resource line will raise an exception when it can't find the resource for member actions which may be happening before you even get to the before_filter line

rails skip_before_filter within method (after other before_filters have been run)

In application_controller.rb I have the following:
before_filter :get_events
before_filter :get_sitemap
def login_required
return true if session[:user]
# If we get to this point, I want to avoid running get_events and get_sitemap
flash[:warning] = 'Please login to continue'
redirect_to login_users_url
return false
end
And in other controllers I have for example:
before_filter :login_required, :except => [:show]
So essentially I have methods running that access the database for all pages except I don't want it to happen when the user is required to log in (i.e., being redirected from a page where normally get_events and get_sitemap are required).
I realize one way of doing this is to run login_required as a before_filter on ALL controllers before any other before_filters are set and then exclude certain controller models but I'd like to know if there's a way of doing it without having to change all my controllers.
For something like this, I usually create an AuthenticatedController (in app/controllers/authenticated_controller.rb):
class AuthenticatedController < ApplicationController
before_filter :require_login
end
Then I derive all controllers requiring authentication from that, specifying a skip_before_filter :require_login for actions I want to exclude on a controller-by-controller basis. For example:
class PlanetsController < AuthenticatedController
skip_before_filter :require_login, only: [:index]
end
This will require you to change all controllers, but only for the purpose of deriving from AuthenticatedController. As far as I know this is a perfectly acceptable way of handling it, and I don't think there's a way outside of monkey patching ActionController::Base to make this apply to all controllers, which is a pretty bad idea for a variety of reasons.
Well after considering Joshua's answer I still couldn't get what I wanted to go for...so what I did was do a little hybrid solution. All controllers still reference ApplicationController, but within ApplicationController I always run the before_filter :login_required FIRST before other before_filters. Redirects in rails seem to stop other before_filters from running, which is what I wanted. In the other controllers I use the skip_before_filter :login_required, :only => [:this_time] wherever necessary.

Specify which controllers to exclude from before_filter

I'm using devise for authentication and have some before_filters in my application controller. Issue I'm seeing is that when I try to logout the before_filter intercepts that and keeps me on the view that's I've setup in the before_filter. Is there any way for me to specify which controllers should be excluded from the application controller or some other file?
In the controller where you want to skip a before filter specified in an inherited controller, you can tell rails to skip the filter
class ApplicationController
before_filter :authenticate_user!
end
class SessionsController < ApplicationController
skip_before_filter :authenticate_user!
end
You can qualify a filter with :only or :except.
before_filter :filter_name, :except => [:action1, :action2]
Or if the filter (as I now see is the case in your situation) is defined in ApplicationController and you want to bypass it in a subclass controller, you can use a skip_before_filter with the same qualifications in the subclass controller:
skip_before_filter :filter_name, :except => [:action1, :action2]
In config/application.rb
config.to_prepare do
Devise::SessionsController.skip_before_filter :authenticate_user!
end
Referenced by:
How to skip a before_filter for Devise's SessionsController?
Answers above are good except:
DEPRECATION WARNING: skip_before_filter is deprecated and will be removed in Rails 5.1. Use skip_before_action instead.
So please use before_action and skip_before_action instead of *-filter.

Resources