Ruby on Rails 3 error: Devise :: LdapAdapter.get_ldap_param undefined

I run: Ruby 1.9.3p0, Rails 3.1.1, Develop 1.4.9, Devise_ldap_authenticatable 0.4.10

I use Devise to authenticate my Rails application through the ldap server. I use the username instead of email for authentication, so naturally the email field in my table is empty.

To request ldap for email, the official way is to add this code to the user model:

before_save :get_ldap_email def get_ldap_email self.email = Devise::LdapAdapter.get_ldap_param(self.username,"mail") end 

This code crashes without trying to do anything with ldap:

 undefined method `mail' for nil:NilClass 

This refers to the line inside the method definition. Log output is no more useful:

 Started POST "/users/sign_in" for 10.50.1.96 at 2011-11-15 11:18:16 -0800 Processing by Devise::SessionsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"<hidden>=", "user"=>{"username"=>"<hidden>", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"} User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."username" = '<hidden>' LIMIT 1 LDAP: LDAP dn lookup: uid=<hidden> LDAP: LDAP search for login: uid=<hidden> LDAP: Authorizing user <hidden> LDAP: LDAP dn lookup: uid=<hidden> LDAP: LDAP search for login: <hidden> Completed 500 Internal Server Error in 251ms NoMethodError (undefined method `mail' for nil:NilClass): app/models/user.rb:14:in `get_ldap_email' 

All lines preceding error 500 are normal successful LDAP authentication not associated with an email request.

I only started learning Ruby, Rails, and Devise last week, so I'm not sure which files will be most important, but here is my user.rb and gemfile model:

 class User < ActiveRecord::Base # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :ldap_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable before_save :get_ldap_email # Setup accessible (or protected) attributes for your model attr_accessible :email, :username, :password, :password_confirmation, :remember_me def get_ldap_email self.email = Devise::LdapAdapter.get_ldap_param(self.username,"mail") end end 

And gemfile:

 source 'http://rubygems.org' gem 'rails', '3.1.1' # Bundle edge Rails instead: # gem 'rails', :git => 'git://github.com/rails/rails.git' gem 'sqlite3' <... unrelated ...> gem 'therubyracer', :platforms => :ruby gem "devise" gem "devise_ldap_authenticatable" 

I tried to restart the server and installed the package since the last GemFile update. In my configuration there is ldap_create_user = true, and the username is the correct field name for users. Is there a mistake in this method? Could there be version incompatibility? I'm not quite sure what else to check, and the rails give me nothing to begin with to continue. I would like to help with this.

+6
source share
4 answers

I also have this problem - my current ldap_authenticatable is to fetch data using Net::LDAP instead of the ldap_authenticatable classes. Of course, a more permanent solution would be to plan ldap_authenticatable , which I can try to do next.

The problem (at least for me) was this: after looking at the ldap_authenticatable code (namely ldap_adapter.rb), I found that the get_ldap_param method get_ldap_param not authenticate with the server when trying to get the parameters if admin_user and admin_password are specified in ldap.yml. Thus, if your LDAP server allows anonymous reading of data, then get_ldap_param will work as advertised. In OpenLDAP (this is what I use for local testing) anonymous read access is set with the "access to" property in slapd.conf:

 access to * by anonymous auth 

But my corporate LDAP does not allow this.

The Net :: LDAP instance in ldap_authenticatable must be created with auth parameters when used to fetch parameters, but this is not the case. There are no auth parameters, so the results are not returned.

So, temporarily, I have the following code in my User model, calling get_ldap_data as a before_save filter:

 def has_ldap_data? [self.email, self.first_name, self.last_name].none? {|v| v.nil?} end def get_ldap_data return true if has_ldap_data? or self.password.nil? ldap = create_ldap ldap.search( :base => ldap.base, :attributes => ['cn', 'sn', 'givenname', 'mail'], :filter => Net::LDAP::Filter.eq('cn', self.username), :return_result => true) do |entry| self.email = entry.mail.first self.first_name = entry.givenname.first self.last_name = entry.sn.first end has_ldap_data? end def create_ldap(password = nil) ldap_config = ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env] ldap_options = { :host => ldap_config["host"], :port => ldap_config["port"], :base => ldap_config["base"], :auth => { :method => :simple, :username => "cn=#{self.username},#{ldap_config['base']}", :password => password || self.password } } ldap_config["ssl"] = :simple_tls if ldap_config["ssl"] === true ldap_options[:encryption] = ldap_config["ssl"].to_sym if ldap_config["ssl"] Net::LDAP.new(ldap_options) end 

Change to your specific needs. It is not perfect, but works until ldap_authenticatable overlapping / putting is taken into account in this use case.

+2
source

So, the problem and the potential solution.

ldap_get_param assumes that anonymous read access to the LDAP server is allowed, and thus tried to link and read using {:method => :anonymous} . If your server does not allow anonymous queries and, for example, Active Directory does not work by default, then your call will fail with the error message described above, which really tries to say "no matching results".

Unfortunately, devise_ldap_authenticable does not allow requiring authentication for read operations, so I went and forked a copy that does. To use it instead, put this in your Gemfile instead of the original:

 gem 'devise_ldap_authenticatable', :git => 'https://github.com/jpatokal/devise_ldap_authenticatable.git' 

And then call get_ldap_param like this:

 Devise::LdapAdapter.get_ldap_param(self.login,"mail",self.password) 

Pay attention to the third parameter. I also passed this as a transfer request for mastering, and you can track this problem here: https://github.com/cschiewek/devise_ldap_authenticatable/issues/94

+2
source

I'm afraid I have no answer for you, but I can say that I have the same exact error as you.

I made a few posts here on StackOverflow, but received no answers. Everything works fine for me until I try to extract additional attributes and: before_save. I traced my eDir server using ndstrace and it says that the question it gets is empty ?! It appears that my selected attribute is not being passed to the ldap server.

+1
source

Perhaps this is due to the version you are using.

Checking the project git repository, I see that the get_ldap_param method was introduced with version 0.4.7.

Make sure that you have no restrictions on the version of the devise_ldap_authenticatable gem in the Gemfile and delete them in this case, then run

 $ bundle update devise_ldap_authenticatable 

it should upgrade your gem to version 0.6.0 (using devise 2.0.1) and this method is present and working.

You can also specify the minimum version in the Gemfile if you think it is:

 gem 'devise_ldap_authenticatable', '~> 0.4.7' 
+1
source

Source: https://habr.com/ru/post/901557/


All Articles