So when I authorize a user with the devise_ldap_authenticatable gem, I get the following logged information:
LDAP: LDAP dn lookup: sAMAccountName=john.smith
LDAP: LDAP search for login: sAMAccountName=john.smith
LDAP: LDAP search yielded 0 matches
LDAP: Authorizing user lt\john.smith
As I understand it, the search fails to return a user, which I would like to find so I could set other attributes based off of LDAP fields (mainly department).
I've checked that this search should work with the following rake task:
desc "LDAP Test"
task ldap: :environment do
ldap = Net::LDAP.new :host => ENV['LDAP_IP'],
:port => ENV['LDAP_PORT'],
:encryption => :simple_tls,
:base => ENV['LDAP_BASE'],
:auth => {
:method => :simple,
:username => ENV['LDAP_LOGIN'],
:password => ENV['LDAP_PASSWORD']
}
if ldap.bind
ldap.search(:base => ENV['LDAP_BASE'], :filter => Net::LDAP::Filter.eq("sAMAccountName", "john.smith"), :attributes => ["sAMAccountName", "department"], :return_result => false) do |entry|
entry.each do |attr, values|
puts "#{attr}: #{values.first}"
end
end
else
puts "Connection failed! Code: #{ldap.get_operation_result.code}, message: #{ldap.get_operation_result.message}"
end
end
Which returns:
dn: CN=John Smith,OU=Temporary Staff,OU=Users,DC=lt,DC=local
department: Bioinformatics
samaccountname: Johh.Smith
Does anyone know why the login search could be failing? My config files are as follows:
devise.rb:
# ==> LDAP Configuration
config.ldap_logger = true
config.ldap_create_user = true
config.ldap_update_password = false
# config.ldap_config = "#{Rails.root}/config/ldap.yml"
config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "lt\\#{login}"}
# config.ldap_check_group_membership = false
# config.ldap_check_attributes = false
config.ldap_use_admin_to_bind = true
ldap.yml:
development:
host: <%= ENV['LDAP_IP'] %>
port: <%= ENV['LDAP_PORT'] %>
attribute: sAMAccountName
base: <%= ENV['LDAP_BASE'] %>
admin_user: <%= ENV['LDAP_LOGIN'] %>
admin_password: <%= ENV['LDAP_PASSWORD'] %>
ssl: true
# <<: *AUTHORIZATIONS
I would use a packet sniffer like Wireshark to see the difference between the LDAP requests in the rake task vs. devise. The UnboundID LDAP SDK for Java also ships with a tool called LDAPDebugger that you can use as a proxy between your app and Active Directory to decode the traffic.
I hope this helps.
Related
Question I am having issues connecting to my Microsoft Active Directory using the devise_ldap_authentication. For some reason I keep getting LDAP search yielded 0 matches when using it with devise and I am 100% certain I am using the correct credentials, so I wrote a test class using 'net/ldap' to see if I could yeild a correct match and presto it works with my test class but, I still can't authenticate with devise_ldap_auth. Any help would be greatly appreciated or help with setting up my config/ldap.yml to match my test class.
Here is my config/ldap.yml
#Environment
development:
host: myldap.mydomain.com
port: 389
attribute: sAMAccountname
base: dc=mydomain, dc=com
admin_user: cn=admin,dc=mydomain,dc=com
admin_password: password
#ssl: false
Here is my devise.rb
Devise.setup do |config|
# ==> LDAP Configuration
config.ldap_logger = true
# config.ldap_create_user = false
# config.ldap_update_password = true
config.ldap_config = "#{Rails.root}/config/ldap.yml"
# config.ldap_check_group_membership = false
# config.ldap_check_group_membership_without_admin = false
config.ldap_check_attributes = true
#config.ldap_use_admin_to_bind = true
# config.ldap_ad_group_check = false
this is what I get back when using ldap with devise.
D, [2016-06-24T07:01:30.558440 #42760] DEBUG -- : LDAP: LDAP dn lookup: sAMAccountName=snow
D, [2016-06-24T07:01:30.558507 #42760] DEBUG -- : LDAP: LDAP dn lookup: sAMAccountName=snow
D, [2016-06-24T07:01:30.558549 #42760] DEBUG -- : LDAP: LDAP search for login: sAMAccountName=snow
D, [2016-06-24T07:01:30.558579 #42760] DEBUG -- : LDAP: LDAP search for login: sAMAccountName=snow
D, [2016-06-24T07:01:30.594029 #42760] DEBUG -- : LDAP: LDAP search yielded 0 matches
D, [2016-06-24T07:01:30.594099 #42760] DEBUG -- : LDAP: LDAP search yielded 0 matches
D, [2016-06-24T07:01:30.594146 #42760] DEBUG -- : LDAP: Authorizing user sAMAccountName=snow,dc=mydomain, dc=com
D, [2016-06-24T07:01:30.594180 #42760] DEBUG -- : LDAP: Authorizing user sAMAccountName=snow,dc=mydomain, dc=com
D, [2016-06-24T07:01:30.611308 #42760] DEBUG -- : LDAP: Not authorized because not authenticated.
D, [2016-06-24T07:01:30.611377 #42760] DEBUG -- : LDAP: Not authorized because not authenticated.
Here is my test class that works to authenticate with ldap on my microsoft AD
require 'net/ldap' # gem install ruby-net-ldap
module Test
class PutAd
SERVER = 'myldap.mydomain.com'
PORT = 389
BASE = 'DC=mydomain,DC=com'
DOMAIN = 'mydomain.com'
ATTR_SV = {
:login => :samaccountname,
:first_name => :givenname,
:last_name => :sn,
:email => :mail
}
def self.authenticate(login, pass)
return nil if login.empty? or pass.empty?
conn = Net::LDAP.new :host => SERVER,
:port => PORT,
:base => BASE,
:auth => { :username => "#{login}##{DOMAIN}",
:password => pass,
:method => :simple }
if conn.bind and user = conn.search(:filter => "sAMAccountName=#{login}").first
return self.new(user)
else
return nil
end
rescue Net::LDAP::LdapError => e
return nil
end
end
end
^This will return my account information if it matches if not it will return nil.
Turns out my company has a different way of authorizing a user. I added the advanced flag to my devise ldap install, and set this accordingly and presto it worked.
==> Advanced LDAP Configuration
config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{login}#mydomain.com"}
I'm using devise_ldap_authenticatable to log in into my Rails app via LDAP. Log in works for user (with username), but does not work for groups: when I try to check if user is in a particular group I get:
'Net::LDAP::BindingInformationInvalidError in
Devise::SessionsController#create
Invalid binding information
Extracted source (around line #244):
raise Net::LDAP::BindingInformationInvalidError, "Invalid binding information" unless (user && psw)
I tried several suggested solutions but they all failed with the error mentioned above.
First attempted solution
I tried changing config.ldap_check_group_membership=false to config.ldap_check_group_membership=true in devise.rb:
config.ldap_create_user = true
config.ldap_check_group_membership = true
config.ldap_check_attributes = false
config.ldap_use_admin_to_bind = false
config.ldap_ad_group_check = true (also tried false with this one)
and setting groups in ldap.yml file like this:
authorizations: &AUTHORIZATIONS
group_base: OU=US,DC=um,DC=com #also tried without group_base, with group_base DC=um,DC=com
required_groups:
- CN=D US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com
- CN=B US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com
later like that:
authorizations: &AUTHORIZATIONS
#also tried without group_base, with group_base DC=um,DC=com
group_base: OU=US,DC=um,DC=com
required_groups:
["memberOf", "CN=D US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com;CN=B US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com"]
Second attempted solution
After this failed, I also tried changing ldap_check_attributes=false to ldap_check_attributes=true in devise.rb:
config.ldap_create_user = true
config.ldap_check_group_membership = false
config.ldap_check_attributes = true
config.ldap_use_admin_to_bind = false
and setting attribute in ldap.yml file like this:
authorizations: &AUTHORIZATIONS
require_attribute:
memberOf: CN=D US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com
development:
host: <%= ENV["LDAP_HOST"] %>
port: <%= ENV["LDAP_PORT"] %>
attribute: 'userprincipalname'
base: 'DC=um,DC=com'
ssl: <%= ENV["LDAP_SSL"] %>
<<: *AUTHORIZATIONS
I have access to AD, I know, that group is correct. When I look at my account there, I see something like this:
memberOf: CN=D US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com;CN=B US
Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com
What am I doing wrong?
Today I managed to find one solution that worked. I've changed devise.rb file like this:
config.ldap_create_user = true
config.ldap_check_group_membership = false
config.ldap_check_attributes = true
config.ldap_use_admin_to_bind = false
and ldap.yml like that:
authorizations: &AUTHORIZATIONS
#group_base:
#required_groups:
require_attribute:
memberOf: CN=D US Workers,OU=Workers,OU=abc,OU=US,DC=um,DC=com
development:
host: <%= ENV["LDAP_HOST"] %>
port: <%= ENV["LDAP_PORT"] %>
attribute: sAMAccountName
base: DC=um,DC=com
ssl: <%= ENV["LDAP_SSL"] %>
admin_user: <%= ENV["LDAP_ADMIN_USER"] %> # currently my own: CN=name surname,OU=Workers,OU=abc,OU=US,DC=um,DC=com
admin_password: <%= ENV["LDAP_ADMIN_PASSWORD"] %> currently my own password
<<: *AUTHORIZATIONS
If I find better solution, I'll post it. Feel free to suggest your way too.
I am trying to list all Organizational Units (OU) from my LDAP directory. I am using the "devise_ldap_authenticatable" gem to authenticate my users. The LDAP sign in works fine. I am trying to get all the OU's now.
I'm new to LDAP, please let me know if my search query is wrong here.
ldap = Net::LDAP.new
ldap.host = "192.168.0.100"
ldap.port = 389
ldap.auth "cn=admin,dc=company,dc=com", "password"
treebase = "dc=company,dc=com"
filter = Net::LDAP::Filter.eq( "objectClass=organizationalUnit","company.com" )
attrs = ["*"]
ldap.search( :base => treebase, :filter => filter, :attributes => attrs, :return_result => false ) do |entry|
puts entry
end
When I ran this, I got nothing returned. I have two OU's in my LDAP, DevOps and Development. There are 5 test users in each.
I'm not sure if this is the right way to do it, but it got me what I wanted and I'm happy with that.
I just removed the filter and retrieved the ou from the entry directly.
ldap.search( :base => treebase, :attributes => attrs, :return_result => false ) do |entry|
puts entry["ou"]
end
The app I am writing has the ability to have a login popup appear and it authenticates against a hard coded username/password constant pair. I would like to authenticate against our central LDAP server. the we dont have a base however we do have a bind_dn string of "cn=USERFOO,ou=it,o=corporate". The variables user/pass are passed in through the basic login box.
I am trying to do this through ActiveLdap however I dont mind using any other library as long as I can validate the credentials through a single sign on against our LDAP server using the HTTPAuth since is written completely in Webrick Ruby. Below is a sample of the function I am calling.
Does anyone have any idea how to do this?
Thanks in advance.
def authenticate_ldap(req,res)
authlabel = "LDAP Authentication"
HTTPAuth.basic_auth(req, res, authlabel) { |user, pass|
ActiveLdap::Base.setup_connection(
:host => 'ldap.internalserver.com',
:port => 389,
:bind_dn => "cn=#{user},ou=it,o=corporate",
:password_block => Proc.new { pass },
)
}
return
end
I figured out a solution. The person who manages our LDAP server provided the incorrect ldap connection string, but even with that it still didn't work.
The solution I discovered that did indeed make a connection with very basic validation is something to this effect for anyone else interested in a very simple ldap authentication popup in pure Ruby.
def authenticate(req,res)
authlabel = 'LDAP Authentication'
HTTPAuth.basic_auth(req, res, authlabel) { |user, pass|
if pass.to_s != ''
ldap = Net::LDAP.new
ldap.host = "ldap.serverfoo.com"
ldap.port = 389
result = ldap.bind_as(
:base => "t=basetreefoo",
:filter => "uid=#{user}",
:password => pass
)
if result
ldap = Net::LDAP.new :host => "ldap.serverfoo.com",
:port => "389",
:auth => {
:method => :simple,
:username => "",
:password => ""
}
group_name = Net::LDAP::Filter.eq("cn", "#{user}")
group_type = Net::LDAP::Filter.eq("groupmembership", "cn=infra,ou=IT,o=Corporate")
filter = group_name & group_type
treebase = "t=basetreefoo"
ldap.search(:base => treebase, :filter => filter) do |entry|
if entry.dn.to_s != ""
puts 'success'
return
end
end
end
end
puts 'fail'
}
end
I am trying to get LDAP authentication to work under Rails.
I have chosen net/ldap since it's a native Ruby LDAP library.
I have tried all possible stuff, specially examples from http://net-ldap.rubyforge.org/classes/Net/LDAP.html but still unable to get it work.
Any ideas?
The best solution I managed to reach is a Model with the following:
require 'net/ldap'
class User < ActiveRecord::Base
def after_initialize
#config = YAML.load(ERB.new(File.read("#{Rails.root}/config/ldap.yml")).result)[Rails.env]
end
def ldap_auth(user, pass)
ldap = initialize_ldap_con
result = ldap.bind_as(
:base => #config['base_dn'],
:filter => "(#{#config['attributes']['id']}=#{user})",
:password => pass
)
if result
# fetch user DN
get_user_dn user
sync_ldap_with_db user
end
nil
end
private
def initialize_ldap_con
options = { :host => #config['host'],
:port => #config['port'],
:encryption => (#config['tls'] ? :simple_tls : nil),
:auth => {
:method => :simple,
:username => #config['ldap_user'],
:password => #config['ldap_password']
}
}
Net::LDAP.new options
end
def get_user_dn(user)
ldap = initialize_ldap_con
login_filter = Net::LDAP::Filter.eq #config['attributes']['id'], "#{user}"
object_filter = Net::LDAP::Filter.eq "objectClass", "*"
ldap.search :base => #config['base_dn'],
:filter => object_filter & login_filter,
:attributes => ['dn', #config['attributes']['first_name'], #config['attributes']['last_name'], #config['attributes']['mail']] do |entry|
logger.debug "DN: #{entry.dn}"
entry.each do |attr, values|
values.each do |value|
logger.debug "#{attr} = #{value}"
end
end
end
end
end
I work on a Devise plugin for Rails 3 that uses LDAP for authentication, you can look at the source to get some ideas, it currently uses net-ldap 0.1.1:
http://github.com/cschiewek/devise_ldap_authenticatable
The actual connecting and authenticating to the LDAP sever is done at:
http://github.com/cschiewek/devise_ldap_authenticatable/blob/master/lib/devise_ldap_authenticatable/ldap_adapter.rb
Lastly, you can look at the sample LDAP server config and Rails 3 app I use to run the tests against:
App: http://github.com/cschiewek/devise_ldap_authenticatable/tree/master/test/rails_app/
Server: http://github.com/cschiewek/devise_ldap_authenticatable/tree/master/test/ldap/