Skip to content

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

Anna Ślimak edited this page Feb 12, 2015 · 19 revisions

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

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

  class CustomFailure < Devise::FailureApp
    def route(scope)
      #return super unless [:worker, :employer, :user].include?(scope) #make it specific to a scope
       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 += %W(#{config.root}/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