Rails4+Devise: "hide" routes when user is not authenticated

1.2k views Asked by At

I am trying to make my admin back-office pages "invisible" for non authenticated users. Meaning when a user goes to something like /admin/my_controller I want to display a 404 custom page, makes him believe this is just a regular 404. And off course when the user is authenticated he will correctly access the controller.

So I got almost everything working, I'm just missing the devise/warden part. I correctly configured 404 error rescue in my Rails app (which is implemented in a controller I named ErrorsController), so when someone goes to a non existing uri such as /nothing_here, my custom 404 page correctly display.

I am trying to use ErrorsController as failure_app which is almost fully working, except that I receive an exception if I log-in with incorrect credential. I am certainly just missing one last detail. Exception is

AbstractController::ActionNotFound at /unauthenticated 
The action 'create' could not be found for ErrorsController

Obviously the create action is supposed to be called from the SessionController not from the ErrorsController. And this is the last bit that is missing. How to achieve this?


Custom 404 configuration

In config/application.rb

config.exceptions_app = self.routes

In config/routes.rb

get '*dummy', to: 'errors#index'

app/controllers/errors_controller.rb

class ErrorsController < ApplicationController
  def index
    display_404
  end
end

Devise configuration

In config/initializers/devise.rb

config.warden do |manager|
  manager.failure_app = ErrorsController
end

Result

  • Accessing a "admin" uri without being authenticated displayed correctly display my custom 404 page
  • Logging-in with devise with correct credential works as expected
  • Logging-in with incorrect credential raises AbstractController::ActionNotFound at /unauthenticated The action 'create' could not be found for ErrorsController
1

There are 1 answers

0
ivopatty On BEST ANSWER

A more graceful way of handling errors when a user is not signed in is adding a method to your application controller. For example display_404 In your display_404 method add

raise ActionController::RoutingError.new('Not Found')

When this method is called it will raise Rails' own error page and log 'Not Found' in the log file. In development this will be shown but on screen but for production it will only be found in the log file, so adding something like 'User was not signed in' is a possibility.

Then using

before_action do
  unless admin_signed_in?
    display_404
   end
end

the error page will be shown when the visitor is not signed in.