Daniel Morrison

Rails Plugin: imap_authenticatable

Update: Thanks to a suggestion in the comments, the plugin now supports SSL.

Let’s say you are a large organization and want to deploy a web app for your employees without making them remember a new password. Assume you don’t have anything cool like LDAP to act as a single point of authentication. What do you do?

Use IMAP.

This is exactly what I did recently for a organization that wanted their thousands of people to be able to use an application I wrote for them, but didn’t want to bother with a new authentication system.

I whipped up a simple Rails plugin to authenticate against their IMAP server. Anyone in the organization can login, and a user in my app is created the first time they successfully do. We now have it running on three apps in the organization.

Installation

Install the plugin as an SVN external:
./script/plugin install -x http://source.collectiveidea.com/public/rails/plugins/imap_authenticatable

or the “regular” way:
./script/plugin install http://source.collectiveidea.com/public/rails/plugins/imap_authenticatable

The plugin expects a Rails Model with a username column. Then put the simple declaration in and specify your host:

class User < ActiveRecord::Base
imap_authenticatable :host => ‘mail.example.com’


end

Additional options

:allow_new_users => true

is a true/false setting which changes whether the included < code >authenticate() method calls < code >find_by_username() or < code >find_or_create_by_username()

:default_domain => ‘example.com’

is for when your IMAP server (mail.example.com) is not what is in your email addresses (daniel@example.com).

:append_domain => false

is a true/false setting which changes whether to strip or append the :default_domain to/from each username.

Authentication

While this plugin takes care of the actual authentication, it doesn’t provide any interfaces for your users. I’ve been using it with Rick Olson’s restful_authentication plugin. You do have to rip some code out and substitute ‘username’ for ‘login’ in a few places (my personal preference).

Questions?

Any questions? Suggestions? If you find this useful, drop me a line!

8 Comments

  1. John Nunemaker — February 07, 2007

    Good idea.

  2. Vincent Palmer — February 08, 2007

    Your “regular” way still includes the -x btw

  3. Arash — February 17, 2007

    Installed it, but now am getting an error “`const_missing’: uninitialized constant Net::IMAP::SSL (NameError)” when I try to script/server
    Why?

  4. Daniel Morrison — February 19, 2007

    @arash: Are you trying to use it with SSL? The code doesn’t currently support this (it should, check back tomorrow, and I’ll package something up).

    As for your error, it could be from OpenSSL not being installed. If you email me the error, I’d be glad to help you out (change the first dot to an @ in my URL).

    @vincent: Thanks, I’ve made the change.

  5. Ron Sweeney — February 21, 2007

    Fantastic Idea! Can’t wait to give this a shot…

  6. Paul Groves — February 07, 2008

    Brilliant

    Thank You!

  7. Daniel Morrison — February 08, 2008

    Paul: Glad you like! Thanks for the comment.

  8. Josh Merchant — April 18, 2008

    Awesome idea. Great for pitching enterprise rails apps.

    Added it to my project… however experienced some problems.

    I don’t know how your particular IMAP server responded to your request, however using a standard email one caused some issues. Even though the login credentials were right, it still seemed to return false.

    Wasn’t a big deal to fix.. just thought you might be interested in the solution:

    login = imap.authenticate(‘LOGIN’, username, password)
    if login[:name] == ‘OK’
    if imap_authenicatable_options[:allow_new_users]
    find_or_create_by_login(username)
    else
    find_by_login(username)
    end
    else
    false
    end
    rescue
    false
    ensure
    imap.disconnect

    Works like a charm :-)

Make a Comment