Firstly you need to know that Active Directory is actually an implementation of LDAP in Windows 2000/2003 Server, and it follows most of the convention in any LDAP server. After that, it is relatively simple to use Active Directory as your authentication server. I’m going to show you how to use Active Directory to authenticate your users, but not to do stuff that changes the Active Directory entries.
What you will need to try this:
- An Active Directory Server which you have an account (this might be your Domain Controller, in Windows parlance)
- The Active Directory Server needs to be accessible through port 389, the standard LDAP port. If you are using a corporate Active Directory, your system administrator would have probably sealed off all ports except those necessary (which normally doesn’t include port 389)
- Ruby/LDAP installed. There are other ways of access LDAP servers including the easier ActiveLDAP but Ruby/LDAP shows a lower level of access. In any case ActiveLDAP actually wraps around Ruby/LDAP so you’ll need that anyway. I’ll include a short writeup on getting Ruby/LDAP on your Windows machine
That’s it! Let’s start.
Getting Ruby/LDAP on your Windows machine
For this I’m assuming you are running Windows XP. For Linux or other variants you can try to build it yourself. The Ruby/LDAP project is an open source project that provides a library for Ruby applications to access LDAP servers. To install it on Windows, the best tutorial I’ve found is at Olivier’s Toolbox. This gem (pun intended) even provided a RubyGem that you can download and install!
> gem install ldap-0.9.5-mswin32.gem
Alternatively you can try following Olivier’s instructions to build the gem or even try it from the source itself if you’re not into Windows.
Authenticating with Ruby/LDAP
This little piece of code below (open sourced under MIT License) is a concise and direct method of authenticating a user with Ruby/LDAP and getting the groups that the user is assigned to.
require 'ldap' class Auth connection = nil host = "localhost" port = 389 dn = nil def initialize(dn,host="localhost",port=389) @host = host @port = port @dn = dn end def login(login, pass) begin conn = LDAP::Conn.new(@host, @port) conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) conn.bind( login, pass ) @connection = conn return true rescue => e false end end def get_member_of(username) result = @connection.search2( @dn, LDAP::LDAP_SCOPE_SUBTREE, "cn=#{username}", ["memberOf"]) members_of = Array.new result.first["memberOf"].each { |str| members_of < < str.split(',')[0].split('=')[1] } members_of end def close @connection.unbind unless @connection == nil @connection = nil end end # testing the code auth = Auth.new("CN=Users,DC=myserver,DC=com",ad.myserver.com, 389) auth.login("sausheong@myserver.com", "password") groups = auth.get_member_of("Sau Sheong Chang") auth.close
Note that your username needs to be in the form of username@domainname. This is apparently a peculiarity with Active Directory, which is different from more standard LDAP servers. The rest of the code is quite self-explanatory. If you want something that allows you to authenticate quickly, this is the shortcut:
require 'ldap' class Auth connection = nil host = "localhost" port = 389 dn = nil def initialize(host="localhost",port=389) @host = host @port = port end def authenticate(login, pass) begin conn = LDAP::Conn.new(@host, @port) conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) conn.bind( login, pass ) return true rescue => e false ensure conn.unbind unless conn == nil conn = nil end end end # test the code auth = Auth.new("ad.myserver.com", 389) if auth.authenticate("sausheong@myserver.com", "password") puts "You're authenticated!" end
Drop me a mail if you have any questions on the code.
I’ve also written an ActiveDirectory module for Ruby that’s available as a gem and is hosted at http://rubyforge.org/projects/activedirectory.
I am new to Rails and starting to trudge through tutorials. How and where is the code above used i.e. in a Rails controller? What would a view look like to see the test data?
Thanks for the post!
M.W. Rails
For Rails you should probably plug this into your login filter somewhere.
Any experience with automatic / invisible logins?
This is a requirement of a new RoR app I am designing for internal government purposes.
There was a page purportedly written by a Microsoft employee that mentioned this, but the page has apparentlt been removed.
Google’s cached version is here:
http://72.14.203.104/search?q=cache:Xx6-552ngMIJ:wiki.rubyonrails.org/rails/pages/WindowsDomainAuthentication+ruby+rails+windows+authentication&hl=en&gl=us&ct=clnk&cd=7&client=firefox-a
Does anyone know anything about this that could post more of an in depth example more than the one line the the linked article?
I don’t have IIS installed to try, but the explanation sounds pretty easy. You have to set IIS authentication to “Integrated Authentication”. This is somewhat like your HTTP authentication except that it will go to your Windows authentication if it is available, or automatically log you in, if you are already logged into the correct domain. The application itself isn’t protected by any of its own access control mechanism, and like HTTP Authentication you can’t control it directly. As the example mentioned however you can use the environment variable “AUTH_USER” to see who is logged in.
Hope this helps.
That helps a bit, but I cannot use IIS (using Red Hat webservers), and I must have automatic logins via active directory. Maybe this cannot be done in Rails without Microsoft’s help… :(
AFAIK you can’t use integrated authentication if you’re not using Windows servers. In fact integrated authentication is specific to IIS only and IIS only runs on Windows servers. But I could be wrong.
Perhaps you can do a workaround like using an activex control to capture the login from your IE and use that to log into the Rails app. It’s a bit hackish though but if I remember correctly some SSO solutions use a similar mechanism.
I’m using an Apache 2.0.55 on Windows XP to run a single-sign-on Mediawiki (PHP). The authentication stuff is done by mod_sspi, which adds NTLM/SSPI authentication to Apache.
Mod_sspi creates the server environment variable REMOTE_USER which contains the name of the authenticated user. I have not tested this setup together with Rails and/or on a non-Windows machine.
The Apache config looks like this:
LoadModule sspi_auth_module modules/mod_auth_sspi.so
…
AllowOverride None
Options None
Order allow,deny
Allow from all
AuthName “Some description”
AuthType SSPI
SSPIAuth on
SSPIOfferSSPI on
SSPIAuthoritative off
SSPIOfferBasic on
SSPIDomain NAME-OF-WINDOWS-DOMAIN
SSPIOmitDomain on
SSPIUsernameCase lower
require valid-user
If SSPIOfferBasic is set to ‘on’, Apache offers basic authentication to the browser, which in turn offers a username/password promt to user where she can enter her Windows username and password.
I expect that this setup should work with Rails too, maybe also on a non-Windows server.
I’m using an Apache 2.0.55 on Windows XP to run a single-sign-on Mediawiki (PHP). The authentication stuff is done by mod_sspi, which adds NTLM/SSPI authentication to Apache.
Mod_sspi creates the server environment variable REMOTE_USER which contains the name of the authenticated user. I have not tested this setup together with Rails and/or on a non-Windows machine.
The Apache config looks like this:
LoadModule sspi_auth_module modules/mod_auth_sspi.so
…
AllowOverride None
Options None
Order allow,deny
Allow from all
AuthName “Some description”
AuthType SSPI
SSPIAuth on
SSPIOfferSSPI on
SSPIAuthoritative off
SSPIOfferBasic on
SSPIDomain NAME-OF-WINDOWS-DOMAIN
SSPIOmitDomain on
SSPIUsernameCase lower
require valid-user
If SSPIOfferBasic is set to ‘on’, Apache offers basic authentication to the browser, which in turn offers a username/password promt to user where she can enter her Windows username and password.
I expect that this setup should work with Rails too, maybe also on a non-Windows server.
Hi,
I would like to know where I can find all the attributes of a user (like “memberof”) in Active Directory in order to retrieve them: for instance, email, phone etc.
Moreover, how could I supply the login name (ie. sausheong@myserver.com) and retrieve the complete name (Sau Sheong Chang)?
Many Thanks.
Ax
i wat where to write code what to write controller,model,view plz provide
Hi,
I would really like to get ldap-0.9.5-mswin32.gem… But all download servers seem to be down… Does anybody have a funktional link/download?
Many Tanks!!!
I was searching for an active directory authentication. Thanks it worked….
What the imbalance creates. ,
Hi there, I discovered your blog by way of Google at the same time as
searching for a comparable topic, your web site came up, it seems great.
I have bookmarked it in my google bookmarks.
I am unable to find the gem “ldap-0.9.5-mswin32.gem”,where can i get this gem.Pls help!!!!
It’s remarkable in support of me to have a web page, which is
good in support of my know-how. thanks admin
This is the perfect website for anyone who hopes to find out about this topic.
You understand a whole lot its almost hard to argue with you (not that I personally would want to…HaHa).
You definitely put a brand new spin on a topic that has been discussed
for many years. Great stuff, just excellent!