Plugins - Simple HTTP Auth

StarAdd to favorites

simple_http_auth

Need to secure a backend or two somewhere, but don’t feel like leveraging a huge, ungainly authentication engine? Don’t care about putting a friendly face on the login screen?

Welp, you want simple_http_auth. It wraps around just the right amount of the Basic HTTP Authentication scheme (RFC 2617), and allows you to easily integrate it into your application, instead of making you adapt your code to my authentication scheme.

(Digest Authentication, Basic Authentication’s grown-up older sibling, is not supported here, because Microsoft effectively spiked it by releasing IE6 and IIS 5.0 with a super magical pony implementation of Digest Authentication which, surprise surprise, totally doesn’t work with Apache, and I’m not in a mood to meet standards-breakers halfway. If you don’t want passwords floating through teh intarweb in plaintext, use SSL. And slap the IE6 dev team if you see them.)

Usage

Overview

  1. Install the plugin. (See previous section)
  2. Add authentication requirements to your controllers as you see fit.
  3. Ride a bike instead of driving your car.

Specifics

simple_http_auth has one method: requires_authentication. To wit:

  class PuppyHeavenController < ApplicationController
    requires_authentication :using => lambda{ |username, password| username != 'cat' }
    # ... actions go here ...
  end

requires_authentication takes a hash of options as its lone argument, only one of which is mandatory: :using. :using is the event handler for any authorization attempt, and is passed two arguments: the username and password provided by the user during their login attempt. :using can be a Proc, as in the example above, or a String or Symbol referencing one of the controller’s methods. For example:

  class PuppyHeavenController < ApplicationController
    requires_authentication :using => :authenticate
    # ... actions go here ...

  private
    def authenticate(username, password)
      return username == 'dog' && password == 'woof'
    end
  end

The event handler for :using should return a Boolean value: true if the user is authorized to access the action, false if not. simple_http_auth doesn’t maintain your user database, make you use a specific model or controller, or anything. You’re responsible for all that.

By default, requires_authentication protects all of the controller’s actions, but this behavior is modifiable by using the :except and :only options:

  class PuppyHeavenController < ApplicationController
    requires_authentication :using => lambda{ |username, password| username != 'cat' },
                            :except => [:publicly_accessible_action]
    # ... actions go here ...
  end

or

  class PuppyHeavenController < ApplicationController
    requires_authentication :using => lambda{ |username, password| username != 'cat' },
                            :only => [:totally_secret]
    # ... actions go here ...
  end

Other options include:

:realm — the authentication "realm," which is usually displayed in the browser’s login dialog. Defaults to "Login Required".

:error_msg — the message displayed on an unsuccessful access attempt. Defaults to "401 Unauthorized: You are not authorized to view this page."

Logging Out

Occasionally someone may want to exit your wonderful application, but I wouldn’t know why. To enable these backsliders (or users in internet cafes, at work, on their sister’s computer, whatever), simple_http_auth provides for logging out:

  class HappyMagicController < ApplicationController
    requires_authentication :using => :whatever,
                            :logout_on => :logout

    def logout
      # logout.rhtml will be displayed after the user logs out
    end
  end

Using HTTP Authentication On Hosting Services

If you’re like most people, you’ve got a little corner on a shared host somewhere, and your Rails apps get managed by someone else. If that’s the case, you make need to jump through a few hoops to get HTTP authentication working. Some virtual hosting configurations of Apache, for example, don’t pass HTTP authentication headers to FastCGI applications like Rails, so you’ll need to add the following line to your public/.htaccess file if HTTP authentication doesn’t appear to work:

  RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]

(This is guaranteed to work on Dreamhost, but I’m not sure about others. Email me with details if you get it working in other environments and need to change this.)

There is another option which influences how simple_http_auth gets the user’s login and password:

:at — an array of header fields where the user’s login and password can be found. Defaults to [‘REDIRECT_REDIRECT_X_HTTP_AUTHORIZATION’, ‘REDIRECT_X_HTTP_AUTHORIZATION’, ‘X-HTTP_AUTHORIZATION’, ‘HTTP_AUTHORIZATION’], which should cover just about everything. These are tried in order, from first to last, and the first header which exists is used as the authentication data. If you’re getting a login dialog, but nothing seems to let you log in (and you’re damn sure your :using handler is working), try fiddling with this to make sure it’s actually receiving the data. For example:

  class PuppyHeavenController < ApplicationController
    requires_authentication :using => lambda{ |username, password| username != 'cat' },
                            :at => ['WOW-WHAT-A-STRANGE-HTTP-SERVER-YOU-HAVE']
    # ... actions go here ...
  end

Credits

Written by Coda Hale .

Released under the MIT license (see MIT-LICENSE).

Thanks to my employer, both for paying me to work with Ruby and Rails on a daily basis, and also for allowing me to release code which I developed for them.

Coda Hale

http://blog.codahale.com/2006/05/11/basic-http-authentication-with-rails-simple_http_auth/

http://svn.codahale.com/simple_http_auth

Rails' (MIT)

  • Currently 3.3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Security

Tags

Comments

Add a comment
viktor tron 27 Oct 2007

I think this is implemented in the current version of rails. http://weblog.rubyonrails.com/2007/9/30/rails-2-0-0-preview-release/comments/17383

class PostsController < ApplicationController USER_NAME, PASSWORD = "dhh", "secret"

before_filter :authenticate, :except =&gt; [ :index ]

def index
  render :text =&gt; &quot;Everyone can see me!&quot; 
end

def edit
  render :text =&gt; &quot;I'm only accessible if you know the password&quot; 
end

private
  def authenticate
    authenticate_or_request_with_http_basic do |user_name, password| 
      user_name == USER_NAME &amp;&amp; password == PASSWORD
    end
  end

end

Niko 21 Feb 2007

Thanks! The rewrite rule works for gpcom.de, too.

Andrew Christensen 13 Oct 2006

I can use this auth system easily on my MacBook using MAMP. But it is using MySQL 4.x. My server is running Apache 1.x and MySQL 5.x. The authorization doesn't work on the server. Can you shed any light?

The authorization basically checks the username and password against a database table. The password is stored as plain text and not encrypted.

Thanks!

Search Plugins

Query syntax

Plugins by Category

Sponsors

Rails Kits: Get Code. Get Moving.
Recruiting software

Have a comment?