Authlogic and LDAP Part 1: Authentication

In the Rails, Authlogic and Single Sign On post, we setup a central authentication app to handle user authentication and sessions centrally.

Let’s move on from that…

All our applications are on a closed network which uses Active Directory (AD). Users first authenticate against AD to get to our login page. They again authenticate against our database to get into our application portal. This is cumbersome and impractical because users in most cases have to remember two passwords.

“We don’t mind logging in twice, but why can’t we just use our same credentials?” they cried…
“You can!” we replied.

All our users use their email address and password for AD authentication. We need to configure our application to use the same credentials for application authentication because our application uses a unique username for logging in – not email address.

First, add this line to your environment.rb file (your version may differ):

config.gem "net-ldap", :lib => false, :version => '>=0.0.5'

Modify the UserSession model by telling authlogic to use our own custom method for password verification:

class UserSession < Authlogic::Session::Base
  verify_password_method :valid_ldap_credentials?
end

Next, we need to modify the User model with 3 things:

1. Tell authlogic to use the email field as the username
2. Tell authlogic NOT to validate the password field against the database
3. Implement our custom password verification method

Your User model should look like this:

class User < ActiveRecord::Base
  acts_as_authentic do |config|
    config.login_field = :email
    config.validate_password_field = false
  end

  protected

  def valid_ldap_credentials?(password)
    Ldap.valid?(self.username, password)
  end
end

Easy enough.

Finally, we create a new class which will talk to AD. The valid? method will return true if the user credentials are valid.

require 'net/ldap'

class Ldap

  LDAP_DOMAIN = 'ad'
  LDAP_SERVER_IP = '10.193.168.52'
  LDAP_USERNAME = 'ldap_username'
  LDAP_PASSWORD = 'ldap_password'

  def self.valid?(username, password)
    init "#{LDAP_DOMAIN}\\#{username}", password
    @ldap.bind
  end

  protected

  def self.init(username, password)
    @ldap = Net::LDAP.new
    @ldap.host = LDAP_SERVER_IP
    @ldap.auth username, password
  end
end

Finally, you can remove the password fields from your users table using a simple migration.

What about security?

Ah, yes. One very important point is that as we are now validating users against AD by allowing them to enter their AD credentials in a web form, you should use SSL to make sure the details cannot be sniffed and that the form details are encrypted.

In Part 2, we’ll look at how to search for users in the Active Directory.

About these ads

Tags: , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: