Skip to content

How To: Use HTTP Basic Authentication

caboteria edited this page Dec 14, 2012 · 2 revisions

Simple HTTP Basic Auth

Devise does have built in HTTP Basic Authentication yet you do need to have two little things in your app to have it working :

  • :database_authenticatable strategy in your user/account model
  • config.http_authenticatable = true in the devise initializer

After that it should work fine, this doesn’t change the behavior of the “web” sign in process. Do not forget to restart your application server for initializer to be reloaded.

Custom HTTP Basic Authentication

Devise has built in HTTP Basic Authentication since version 1.0. However, the steps below are still useful if you want to provide a custom failure response from your application.

Devise relies on Warden, which is a rack framework for authentication. On its own, Warden tries to provide a custom response to all unauthenticated requests, by something called failure_app, which is a valid rack app. In Devise, this app can be found at lib/devise/failure and it simply redirects you to the login page.

That said, when using a Digest HTTP Authentication in Rails, the first request to a protected page returns a 401 status with a realm (which tells the user that basic http authentication needs to be performed). Since it has status 401, Warden will try to handle it, it will redirect you to the login page, and your user will never see the basic authentication request. How to fix that?

You just need to tell Warden that you are providing a custom failure, so it won’t do anything at all. A simple code that performs http authentication is below:

    def http_authenticate
      authenticate_or_request_with_http_digest do |user_name, password|
        user_name == "foo" && password == "bar"
      end
      warden.custom_failure! if performed?
    end

Notice that since Devise 1.2, Warden won’t automatically intercept 401 by default, so you don’t need to call warden.custom_failure! as above.

When using Devise + Rails together with HTTP Auth via Nginx or Apache

Note that the strategy :database_authenticatable automatically responds to HTTP Auth, whenever Auth-Headers are sent. Currently, this feature can be enabled (it is disabled by default) in devise by setting config.http_authenticatable = true (follow this discussion). Failing that, when you protect your application via HTTP Auth directly from your webserver (e.g. Nginx, or Apache), whenever a user tries to login to his account, devise will interpret the current HTTP Auth (meant only for the webserver) as an attempt to login. This login will fail, since devise most likely expects something else than your webserver.

To prevent this collision, you will either need to deactivate the HTTP Authentication on the webserver, or prevent it from being passed on to the application (Nginx for example cannot do this by default), or protect your application in some other way (e.g. with a global session-based before_filter and a simple login form).

Here’s a simple rack middleware to prevent the HTTP Authentication header from being passed on to your application.

Problems after removing HTTP authentication

If you have removed HTTP authentication from your application, the browser may continue to send its saved user name and password prior to each page request even though it is no longer needed. When this happens on a login page, Devise will use the browser’s saved credentials instead of the user supplied information likely causing login to fail. Accessing the application from a URL without saved HTTP information or simply closing and restarting the browser should alleviate the problem.

Clone this wiki locally