Question

I am trying to integrate devise_ldap_authenticatable into my app. Our company has ldap servers that house the pertinents for users in different locations. The data in these servers do not overlap. My issue is that I cannot get the devise_ldap_authenticatable gem to use our ldap search tree. I can specify only one ou=. Any sense of a search-path is lost in the ldap.yml file. The following ldap file works, but only for users in cityMain.

development:
  host: ldap.myCompany.com
  port: <port>
  attribute: uid
  base: ou=people,ou=cityMain,dc=myCompany,dc=com
  admin_user: uid=proxy-generic,ou=cityMain,dc=myCompany,dc=com
  admin_password: pw
  ssl: true

If I change cityMain to city1, only users in city1 can log-in. What I need to do is one of two things.

1) use the ldap.conf file which is provided by our IT department

-or-

2) allow for multiple location ou's, maybe with an ldap filter statement (i.e:

development:
  host: ldap.myCompany.com
  port: <port>
  attribute: uid
  base: ou=people,(|(ou=city1)(ou=city2)(ou=city3)(ou=city4)(ou=cityMain)),dc=myCompany,dc=com
  admin_user: uid=proxy-generic,ou=cityMain,dc=myCompany,dc=com
  admin_password: pw
  ssl: true

As of this point, I cannot log-in using the filter in the second snippet. Thanks in advance for looking at this. Any help is much appreciated.

Was it helpful?

Solution

I have figured out a workaround. I edited the devise_ldap_adapter to accept an array of base configurations. In the ldap.yml file:

base: ou=people,ou=cityMain,dc=myCompany,dc=com

becomes

base: ["ou=people,ou=cityMain,dc=myCompany,dc=com",
       "ou=people,ou=city1,dc=myCompany,dc=com",
       "ou=people,ou=city2,dc=myCompany,dc=com",
       "ou=people,ou=city3,dc=myCompany,dc=com",
       "ou=people,ou=city4,dc=myCompany,dc=com"]

and the devise_ldap_authenticatable ldap_adapter.rb file is then edited to iterate through these base array elements:

    def self.valid_credentials?(login, password_plaintext)
      ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#              {Rails.root}/config/ldap.yml")).result)[Rails.env]
  options = {:login => login,
             :password => password_plaintext,
             :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
             :admin => ::Devise.ldap_use_admin_to_bind}
  resource = LdapConnect.new(options)
  resource.authorized?           
end

becomes:

    def self.valid_credentials?(login, password_plaintext)
  ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env]
  bases = ldap_config["base"]
  options = {:login => login,        
             :password => password_plaintext,       
             :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
             :admin => ::Devise.ldap_use_admin_to_bind}
  bases.each do |base|      
    # Initializer now accepts a second parameter: base
    resource = LdapConnect.new(options, base)
    if resource.authorized?
      return true
    end
  end
  false
end

Edit the initializer to accept a second parameter, "base" and assign the value to @ldap.base

def initialize(params = {}, base)
  # def initialize(params = {})
    ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env]
    ldap_options = params
    ldap_config["ssl"] = :simple_tls if ldap_config["ssl"] === true
    ldap_options[:encryption] = ldap_config["ssl"].to_sym if ldap_config["ssl"]

    @ldap = Net::LDAP.new(ldap_options)
    @ldap.host = ldap_config["host"]
    @ldap.port = ldap_config["port"]
    # Use base parameter here
    @ldap.base = base
    # @ldap.base = ldap_config["base"]
    @attribute = ldap_config["attribute"]
    @ldap_auth_username_builder = params[:ldap_auth_username_builder]

    @group_base = ldap_config["group_base"]
    @required_groups = ldap_config["required_groups"]        
    @required_attributes = ldap_config["require_attribute"]

    @ldap.auth ldap_config["admin_user"], ldap_config["admin_password"] if params[:admin] 
    @login = params[:login]
    @password = params[:password]
    @new_password = params[:new_password]

  end

Bob's your uncle.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top