2

I am trying to rewrite an older app that was created with PHP/MySQL. The authentication system used has a users table in the database that stores username, email etc... but NOT passwords.

Whenever the user logs in it first checks the database to see if the user exists if not then returns a login error. If the user exists in the local database then it tries to bind to the active directory using the username/password combination entered by the user and creates a session if successful.

What is the best way to accomplish this using Rails?

1
  • Are you asking about Rails 4.0+ ? Commented Jan 9, 2014 at 21:38

2 Answers 2

3

Ruby's Net::LDAP library is pretty good.

Here's a simplified version of what I've been using for years:

# sessions_controller.rb
def create
  user = User.find_by_login(params[:login])
  if user && Ldap.authenticate(params[:login], params[:password])
    self.current_user = user
    Rails.logger.info "Logged in #{user.name}"
    flash[:notice] = "Successfully Logged In!"
    redirect_back_or_default root_url
  else
    flash[:alert] = "Invalid User credentials"
    render :new
  end
end

# lib/ldap.rb
# Ldap.authenticate('user','password')
# Returns true if validated
# Returns false if invalidated
# Returns nil if LDAP unavailable
require 'net/ldap'
class Ldap
  def self.config
    # this is actually loaded from a yaml config file
    {
      :domain => 'YOURDOMAIN',
      :host   => '10.10.10.100'
    }
  end

  def self.authenticate(login, password)
    conn = Net::LDAP.new(
      :host       => config[:host],
      :port       => 636,
      :base       => "dc=#{config[:domain]}, dc=local",
      :encryption => :simple_tls,
      :auth       => {
        :username => "#{login}@#{config[:domain]}.local",
        :password => password,
        :method   => :simple
      }
    )
    Timeout::timeout(15) do
      return conn.bind ? true : false
    end
  rescue Net::LDAP::LdapError => e
    notify_ldap_admin(config[:host],'Error',e)
    nil
  rescue Timeout::Error => e
    notify_ldap_admin(config[:host],'Timeout',e)
    nil
  end

  def self.notify_ldap_admin(host,error_type,error)
    msg = "LDAP #{error_type} on #{host}"
    RAILS_DEFAULT_LOGGER.debug(msg)
    DeveloperMailer.deliver_ldap_failure_msg(msg,error)
  end
end
Sign up to request clarification or add additional context in comments.

Comments

0

Check out the devise and devise_ldap_authenticatable libraries.

4 Comments

from the documentation, devise_ldap_authenticable cannot be used along with database authenticable module.
You can do it, just have to write your own strategy
Can you explain that more please? Is there another question that digs into that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.