Net::LDAP has the advantage of being the only pure Ruby LDAP library.
First install the Net::LDAP gem from http://rubyforge.org/projects/net-ldap/
gem install ruby-net-ldap
Here is a sample authentication function:
require_gem 'ruby-net-ldap'
require 'net/ldap'
#Bind with the main credential and query the full DN of the email address
#given to us as a parameter, then unbind and rebind as the user.
def self.authenticate(mail,password)
ldap_con = initialize_ldap_con('myusername','mypassword')
treebase = "DC=mydomainname,DC=mydomain"
mail_filter = Net::LDAP::Filter.eq( "mail", mail )
op_filter = Net::LDAP::Filter.eq( "objectClass", "organizationalPerson" )
dn = String.new
ldap_con.search( :base => treebase, :filter => op_filter & mail_filter, :attributes=> 'dn') do |entry|
dn = entry.dn
end
login_succeeded = false
unless dn.empty?
ldap_con = initialize_ldap_con(dn,password)
login_succeeded = true if ldap_con.bind
end
login_succeeded
end
private
def self.initialize_ldap_con(user_name, password)
Net::LDAP.new( {:host => '10.9.2.33', :port => 389, :auth => { :method => :simple, :username => user_name, :password => password }} )
end
Cleaner version using the new #bind_as method from the latest version (Net::LDAP 0.0.4) available via Gem or RubyForge
module LDAP
#Bind with the main credential and query the full DN of the email address
#given to us as a parameter, then unbind and rebind as the user.
#
#If login succeeds return an LDAPUser object
#If login fails return false
def self.authenticate(identifier,password)
if identifier.to_s.length > 0 and password.to_s.length > 0
ldap_con = initialize_ldap_con
email_filter = Net::LDAP::Filter.eq( Settings.ldap_server_user_identifier_attribute_type, identifier )
if rs = ldap_con.bind_as(:filter => email_filter, :password => password)
groups = [self.derive_group(rs[0].dn, Settings.ldap_server_group_identifier_attribute_type)]
return User.new(identifier, groups, self)
else
return false
end
end
end
private
def self.initialize_ldap_con
hsh = {:host => Settings.ldap_server_host, :port => Settings.ldap_server_port}
hsh[:base] = Settings.ldap_server_tree_base
hsh[:auth] = { :method => :simple, :username => Settings.ldap_server_user_name, :password => Settings.ldap_server_password }
Net::LDAP.new( hsh )
end
#takes a DN and derives the name of the group from it
#returns name of group (in lower case)
def self.derive_group(dn, group_identifier_attribute_type)
first_ou = dn.downcase.match(/,#{group_identifier_attribute_type.downcase}=[^,]+/).to_s
group = first_ou[group_identifier_attribute_type.length+2,first_ou.length]
end
end
%{Q: Where do you put this stuff?}
%{Q: How is it then used?}
This finally worked for me … just use your username, password & hostname. Note that CORP is my domain name. Also note that the username and password should be contained in SINGLE QUOTES unless you have some reason to use double quotes…. that messed me up for a while.
require 'rubygems'
require 'net/ldap'
user = 'CORP\my_username'
pass = 'my_password'
ldap = Net::LDAP.new :host => "x.x.x.x", :port => 389, :auth => {:method => :simple, :username => user, :password => pass}
p (ldap.bind) ? "Authorization Succeeded!" : "Authorization Failed: #{ldap.get_operation_result.message}"
In the event that you have users spread out amongst a number of OU’s and you use an LDAP server that requires you to bind with the full DN rather than just the username, you can use something like this to authenticate:
require 'rubygems'
require 'net/ldap'
username = 'jdoe'
password = 'mypass'
ldap = Net::LDAP.new(:host => 'ldap.example.com', :base => 'dc=example,dc=com')
filter = Net::LDAP::Filter.eq('uid', username)
ldap.search(:filter => filter) {|entry| username = entry.dn}
ldap.auth(username, password)
if ldap.bind
# authentication succeeded
else
# authentication failed
end