Question

In my Rails 2.3 app we have an admin section that is protected by basic HTTP authentication. This has worked on our production and staging environments for years. Recently I setup a new environment to demo a long-running feature branch, and to differentiate between that and the other staging server I set it to run using a custom "redesign" environment. So now my Admin::BaseController looks like this:

class Admin::BaseController < ApplicationController
  before_filter :verify_access

  def verify_access
    logger.info "\n\n-- running verify_access filter on #{RAILS_ENV}\n"
    if %w(production staging redesign).include?(RAILS_ENV)
      logger.info "\n-- should send authentication\n"
      authenticate_or_request_with_http_basic("Restricted Access") do |username, password|
        logger.info "\nauthentication received: {username}::#{password}\n"
        username == 'myusername'
        password == 'mypassword' 
      end 
    end
  end
end

For some reason, the new server ALWAYS responds Unauthorized and doesn't offer any login dialog, not even if I quit and reopen my browser, not even if I use a private browser session, not even if I specify a username in the URL (i.e. http://username@www.mysite.com/admin). It just automatically redirects me to the root and adds ?unauthorized=true to the query string, though no where in my application code is there anything that would do that.

I know it's hitting the verify_access filter, because I can see it in the log file:

Processing Admin::OrdersController#index (for xx.xx.xx.xx at 2014-05-09 05:56:59) [GET]
  Parameters: {"action"=>"index", "controller"=>"admin/orders"}

-- running verify_access filter on redesign

-- should send authentication

Filter chain halted as [:verify_access] rendered_or_redirected.
Completed in 25ms (View: 21, DB: 1) | 401 Unauthorized [http://www.mydomain.com/admin/orders]


Processing IndexController#show (for xx.xx.xx.xx at 2014-05-09 05:56:59) [GET]
  Parameters: {"action"=>"show", "controller"=>"index", "unauthenticated"=>"true"}
Rendering index/show
Completed in 30ms (View: 27, DB: 3) | 200 OK [http://www.mydomain.com/?unauthenticated=true]

In the networking panel in Chrome, the request for the admin page actually shows that it's receiving a 302 Found response from the server, even though Rails is sending a 401 Unauthorized.

GET /admin/orders HTTP/1.1
Host: www.mydomain.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: _myapp_session=xxx

HTTP/1.1 302 Found
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive
Status: 302
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.2.10
Location: /?unauthenticated=true
Server: nginx/0.7.65 + Phusion Passenger 2.2.10 (mod_rails/mod_rack)

The new server is a clone of the original staging server, so the architecture is exactly the same, and all the same chef recipes were used. Any ideas on what's going on here?

Was it helpful?

Solution

Turns out HTTP Basic Auth was tripping over Devise, one of the new features in this branch. Updating my verify_access method to the following solved the problem:

def verify_access
  if %w(production staging redesign).include?(RAILS_ENV)
    authenticate_or_request_with_http_basic("Restricted Access") do |username, password|
      username == 'username' && password == 'password'
    end
  end
  warden.custom_failure! if performed?
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top