I’ve had this article sitting around in Draft for quite some time now and finally got around to putting some finishing touches on. Needless to say, I’ve jumped onto the Ruby on Rails bandwagon along with a lot of other people, and continue to be amazed as I learn more and more about the framework. Currently I’m in the process of mocking up a new application in Rails that will need to tie back into Notes quite a bit. The first step in this process was to get Notes logins to work in the Rails app which was wasn’t too rough.
Our Domino server was already configured to run LDAP and allowed anonymous access which makes things a little tougher. I had to search around quite a bit and piece together information on how to connect to LDAP via Ruby and how to create a simple authentication system and login page.
To start things off you need the Net::LDAP library, you can download it from the ruby forge site, or just grab it with Gem.
gem install ruby-net-ldap
Next I created a module in the Rails’ /lib folder to hold the LDAP connection and authenticate method.
EDIT 9/20/2007:It seems I wasn’t very clear here, this code below was placed into “ldap_connect.rb” within the lib folder. It is then included into the rails application with the require statement below.
require 'net/ldap' module LDAP def self.authenticate(user,password) if user == "" || password == "" return false end ldap_con = Net::LDAP.new({:host => 'your.dominoserver.com', :port => 389,:auth=>{:method=>:simple,:username => user, :password => password } } ) return true if ldap_con.bind return false end end
This code is pretty simple, its going to first do a reality check to make sure that a name and password were entered at all (necessary because we allow anonymous access), then it will attempt to create (bind) a connection to the ldap server using the username and password entered. Now on to the controller, I let rails generate the shell with a quick
script generate controller login
Instead of starting from scratch I found a nice simple base on the Rails Wiki. Really the only parts to worry about are the call to the LDAP.authenticate function, and the mention up top to skip_before_filter :authenticate (I’ll go into this more in a moment).
require 'ldap_connect' class LoginController < ApplicationController skip_before_filter :authenticate def index end def authenticate if session[:person] = LDAP.authenticate(params[:login][:name], params[:login][:password]) session[:username] = params[:login][:name].capitalize_each if session[:return_to] redirect_to_path(session[:return_to]) session[:return_to] = nil else redirect_to :controller => "inspections" end else flash[:notice] = "Login failed!" redirect_to :action => "index" end end # logout # clears the session def logout session[:person] = nil session[:username] = nil flash[:notice] = "Logged out" redirect_to :action => "index" end end
This is a pretty simple controller, it’s basically passing through the values entered to the authenticate method above and then redirecting the user depending on the result of the authentication. It does have some niceness where it previously stored the page the user was trying to access and redirects them to that page if they successfully login. Something is still missing… we need to tell the application to force people to login if they haven’t already. Since we want this to happen on any page they might go to we place this code in the application.rb controller. A few quick lines will do the trick
class ApplicationController < ActionController::Base before_filter :authenticate filter_parameter_logging "password" protected def authenticate unless session[:person] session[:return_to] = @request.request_uri redirect_to :controller => "login" return false end end end
before_filter will take care of calling authenticate before displaying any page. Authenticate checks to see if they have our session variable set and will redirect them to login if need be. A quick note about the filter_parameter_logging, this is good to have in place otherwise all passwords will be recorded in plain text log files…:P
The final piece needed is a simple view to display the login fields. By default rails is configured to look for the index method of any controller (this can be changed). To keep things simple I made the login page views\login\index.rhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <title>Login</title> </head> <body> <%= start_form_tag :action => 'authenticate' %> <fieldset> <div class="form-element"> <label for="name">Username </label> <%= text_field 'login', 'name' , {:class=>"text-input"} %> </div> <div class="form-element"> <label for="password">Password </label> <%= password_field 'login', 'password' , {:class=>"text-input"} %> </div> </body> </html>
That’s it… not entirely simple, but really not bad once you get the hang of Rails.

hey tried your method …gives an error for ldap_connect ..can you please help me with that.
raghu
May 29th, 2007
What sort of error are you getting? I think most of that code was copy/paste straight from what I have that’s functional for me.
Rich Waters
May 29th, 2007
hi.,
am new to rails., is there any server i need to install for net ldap., or is this gem enough to implement ldap in my application??.,can u pls explain me in detail??? if i need to install or configure anyhthing , how to do that?? please help me…
Carolin Raji
May 31st, 2007
Hi Carolin,
It really depends on your setup. My experience specifically has been with hooking up Rails to an already existing LDAP server which is integrated with our Lotus Notes/Domino system. You could certainly tie into another LDAP source, but somewhere there needs to be an LDAP server configured and allowing connections from your Rails application. If you don’t already have an LDAP server up and running you could look into a more simple Rails-only form of authentication or perhaps Open LDAP (http://www.openldap.org/)
Rich Waters
May 31st, 2007
Hi,
your code is not accepted by some IDE like Aptana
it didn’t take your code please copy correct format
Ravi Vardhan
September 20th, 2007
Hi
i cannot understand two require statements in two files
please explain
require ‘net/ldap’ in lib folder
and reuire ldap_connect in loginController
i have got error
uninitialized constant LoginController::LDAP
please help on this
bye
bewan
September 20th, 2007
Ravi,
I’m surprised the code isn’t functional, there’s nothing specific that should cause issues with Aptana. Perhaps it is copying and pasting the html so you may need to convert over characters like <
Rich Waters
September 20th, 2007
Bewan,
That seems to be an issue I wasn’t extremely clear on. The ‘net/ldap’ require is what pulls in the ruby-net-ldap gem that was required. ‘ldap_connect’ is what I named my module in the lib folder, you may need to adjust this to whatever filename you chose. I’ll make a quick edit above to make sure that section is clear. Not having the correct name there would cause the error you stated.
Rich Waters
September 20th, 2007
Hi,
i have followed your steps as it is but i got below error.please respond to my problem
thank u
“invalid binding information”
RAILS_ROOT: script/../config/..
Application Trace | Framework Trace | Full Trace
/var/lib/gems/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:1097:in `bind’
/var/lib/gems/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:701:in `bind’
Bharath
September 21st, 2007
Hi,
I have followed your steps as it is but i got below error.please respond to my problem
thank u
Net::LDAP::LdapError in LoginController#authenticate
“invalid binding information�
RAILS_ROOT: script/../config/..
Application Trace | Framework Trace | Full Trace
/var/lib/gems/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:1097:in `bind’
/var/lib/gems/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:701:in `bind’
Bharath
September 21st, 2007
Bharath,
Are you sure that you configured the connection information to your server properly? Also if it is a Notes server, do you have LDAP turned on? It sounds like there’s a problem even connecting to your LDAP server.
Rich Waters
September 21st, 2007
Hi Rich Waters,
This is Bharath.Thansks for gave response to my problem.
But i have used below information to connect LDAP in lib/ldap_connect.rb
require ‘net/ldap’
module LDAP
def self.authenticate(user,password)
if user == “” ||password == “”
return false
end
ldap_con = Net::LDAP.new({:host =>’192.168.0.12′,:port =>389,
:auth => {:method=>:simple,:ou=>”People”,:uid=>user,:password=>password}})
return true if ldap_con.bind
return false
end
end
Bharath
September 24th, 2007
is there any wrong please suggest me.(Ldap Server is working fine with above data.no problem in LDAP)
Bharath
September 24th, 2007
i am getting an error showing
uninitialized constant LoginController::LDAP
/usr/lib/ruby/gems/1.8/gems/activesupport-1.4.2/lib/active_support/dependencies.rb:477:in `const_missing’
app/controllers/login_controller.rb:8:in `authenticate’
-e:4:in `load’
-e:4
could you plz solve my comment
thanks ,,
sri
September 25th, 2007
Bharath,
I don’t know that you can include the ou=>”People” bit in the initial connection. They way I had it functioning we allowed all LDAP users to bind to the server and begin querying. I would check out http://wiki.rubyonrails.org/rails/pages/HowtoAuthenticateWithRubyNetLdap for some more info.
Rich Waters
September 25th, 2007
Sri,
not quite sure what the issue is, you’re using a separate controller where I put it in application.rb for my example. What is line 8 in your login_controller?
Rich Waters
September 25th, 2007
hi Rich,
i am getting error like this
NameError in LoginController#authenticate
uninitialized constant LDAP::NET
and my line 8 contains
def authenticate
if session[:person]=LDAP.authenticate(params[:login][:name],params[:login][:password])
session[:username]=params[:login][:name].capitalize_each
if session[:return_to]
sri
September 26th, 2007
hi,
how can we know that the application was connected to ldap server or not ,where the code takes place that you mentioned
sri
September 26th, 2007
hi rich waters,
and now i am getting error like this
Net::LDAP::LdapError in LoginController#authenticate
invalid binding information
RAILS_ROOT: script/../config/..
My LDAP server was working fine
could you suggest me immediately its urgent
sri
September 26th, 2007
hi Rich waters,
finally i got connected to server
but the thing is How to check whether particular account is existing or not ,i mean how to search ant retrieve attributes of existing user accounts
thank u..
sri
September 27th, 2007
Sri,
There has been a lot of interest in this area, I may write some additional future articles about LDAP in Rails.
Here’s a method that I use to grab a single record and have access to it’s attributes.
def self.get_user(user)
ldap = Net::LDAP.new( { :host => “blah”, :port => 389, :base => “” } )
cn_filter = Net::LDAP::Filter.eq( “cn”, user )
person = ldap.search( :filter => cn_filter )
return person[0]
end
Rich Waters
October 10th, 2007
Hi Rich,
Thanks for the great article, it’s very helpful. I haven’t attempted to implement this idea yet but I was wondering if you’ve done any particular ACL checking? For example if you have an application that you wish to allow access only to users in the group “Administrators”, does that information come back in the ldap search?
Thanks!
-Irene
Irene Ros
December 7th, 2007
Irene,
I have taken this further, and have used groups for a basic role system in an application I’m currently working on. I’ll work on a follow up article and can provide a function to easily test if someone is a member of a specific group.
Rich Waters
December 7th, 2007
I was able to get LDAP authentication up and running. However, if ldap.bind never seems to return false. If I have valid login info, it will return true sometimes, and if I use invalid info, it just hangs indefinitely.
Brad
January 3rd, 2008
Thanks for the Article Rich,
Is there a way to make the username param search based on uid instead of DN? I would rather have someone login with a uid instead of their full name… Which seems to be the only thing I can get working.
Cheers,
Jay
Jay
April 2nd, 2009
Hi rich i am also getting this error
invalid binding information/home/mubashir/.gem/ruby/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:1097:in `bind’
/home/mubashir/.gem/ruby/1.8/gems/ruby-net-ldap-0.0.4/lib/net/ldap.rb:701:in `bind’
/home/mubashir/mis/lib/ldap_connect.rb:11:in `authenticate’
/home/mubashir/mis/app/controllers/login_controller.rb:10:in `authenticate’
can you plz guide me how i can resolve this problem.
mushi
July 13th, 2009
This code doesn’t work, and even if u by chance get the login screen it doesn’t have a submit button, ruby on the rails is making me very sad and it’s a big dissappiontment
florian
September 11th, 2009
Well for me the error was simple:
:uid=>user is false
:username=>user
and it works fine.
Claus-Christian Ude
October 28th, 2009