Skip to content

How To: Redirect to a specific page when the user can not be authenticated

Kyle Fox edited this page Aug 12, 2018 · 19 revisions

If a user is not authenticatable you can redirect to a specific page.

Tip: If you want to redirect to the sign up path (new registration) instead of the sign in path (new session), see this article.

For this example we want to use the entire URL with a particular sub-domain. Devise uses the path not the entire URL by default. The workaround is to use a custom failure app inherited from Devise failure app.

Rails 3, Rails 4 & Rails 5

  class CustomFailure < Devise::FailureApp
    def redirect_url
       new_user_session_url(:subdomain => 'secure')
    end

    # You need to override respond to eliminate recall
    def respond
      if http_auth?
        http_auth
      else
        redirect
      end
    end
  end

And add the following in config/initializers/devise.rb:

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

If you’re getting an uninitialized constant CustomFailure error, and you’ve put the CustomFailure class under your /lib directory, make sure to autoload your lib files in your application.rb file, like below

  config.autoload_paths << Rails.root.join('lib')

Rails 2.3.x

  class CustomFailure < Devise::FailureApp
    include ActionController::UrlWriter
    def respond!
      options = @env['warden.options']
      scope   = options[:scope]

      redirect_path = if mapping = Devise.mappings[scope]
        eval("new_#{scope}_session_url(:host => 'secure.domain.com', :protocol => 'https')")
      else
        "/#{default_url}"
      end
      query_string = query_string_for(options)
      store_location!(scope)

      headers = {}
      headers["Location"] = redirect_path
      headers["Location"] << "?" << query_string unless query_string.empty?
      headers["Content-Type"] = 'text/plain'

      [302, headers, ["You are being redirected to #{redirect_path}"]]
    end
  end

And add the following in config/initializers/devise.rb:

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

See further explanation at Stackoverflow

Clone this wiki locally