Many enterprises have an Active Directory infrastructure setup. Wouldn’t it be nice if your jruby app could exploit this already in place infrastructure to authenticate your users. ruby-net-ldap has been around for a while and allows users to do exactly this with MRi ruby and now thanks to Ola bini it is now possible with jruby.
First things first, we need to install the gem,
jruby -S gem install jruby-ldap
once the gem has been installed we can then fire up a console, execute the following command in your rails app directory
jruby -S script/console
once the console is booted enter
require 'ldap' conn = LDAP::Conn.new(host="IP Address of your server", port="LDAP Port, typically 389")
this should then return you a connection object which we can use to now use to bind to the server and form there on search the directory tree. to bind to the server we simply supply some credentials. NB: I had a problem initially as some of the usernames contained periods(.) i.e. foo.bar and this caused a few problems for these accounts, the solution was to fully qualify the name (foo.bar@componentworkshop.com)
conn.bind("username","password") do |bound_conn|
conn.search("cn=Users,dc=domain,dc=com", LDAP::LDAP_SCOPE_SUBTREE, "(&(objectclass=person))",["name","mail"]) do |entry|
puts "#{entry.inspect}"
end
endwhen ran this code will render each entry that the search has found, firstly it creates a binding which authenticates you on the server. We then pass a block to search the LDAP tree. The search method takes a few parameters, for info about these parameters have a look at Suns documentation
Now we have verified, that everything is setup and working. We can go ahead and use our new found wisdom to authenticate users from our login controller. The following code provides an example on using jruby-ldap to authenticate the users, and then add them to a user model if they do not already exist in the database.
def authenticate
attrs = ["name","samAccountName", "cn", "mail", "department", "manager"]
conn = LDAP::Conn.new(host = "127.0.0.1", port = 389)
conn.set_option(LDAP::LDAP_OPT_PROTOCOL_VERSION, 3)
domain = "foobar.com"
conn.simple_bind(login + "@" + domain, password) do |conn|
conn.search("cn=Users,dc=componentworkshop,dc=local", LDAP::LDAP_SCOPE_SUBTREE, "(samAccountName=#{login.to_s})", attrs) do |entry|
user = User.find(:all, :conditions => ["login = ?", login]).first
if(!user)
user = User.create!(:name => entry.vals('cn').to_s, :login => entry.vals('samAccountName').to_s, :email => entry.vals('mail').to_s)
end
return user;
else
return User.find(:all, :conditions => ["login = ?", entry.vals('cn')]).first
end
end
end
end
About
We are a small British company that produces business-oriented software and solutions. These articles are a product of our daily work - information that we think might be useful to share. We hope you find them useful.
Our Software
These are some of our products. Several are open source, some are web-based and others are proprietary:
Categories
- .NET (10)
- Apple (2)
- Business (5)
- CSS (1)
- HTML (2)
- Innovation (4)
- Java (4)
- Javascript (1)
- Leadership (1)
- MySQL (2)
- Oracle (6)
- Postgres (1)
- Programming (5)
- Rails (4)
- Ruby (10)
- SQL Server (9)
- Subversion (1)
- Web (5)
- Windows Server (2)
Archives
- July 2010 (2)
- September 2009 (5)
- August 2009 (1)
- July 2009 (12)
- June 2009 (16)
- May 2009 (3)