saush

Ruby/Rails user authentication with Microsoft Active Directory

Posted in Rails, Ruby by sausheong on July 18, 2006

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.

About these ads

20 Responses

Subscribe to comments with RSS.

  1. Justin Mecham said, on July 19, 2006 at 12:05 am

    I’ve also written an ActiveDirectory module for Ruby that’s available as a gem and is hosted at http://rubyforge.org/projects/activedirectory.

  2. MW said, on July 19, 2006 at 2:33 am

    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

  3. sausheong said, on July 19, 2006 at 8:32 am

    For Rails you should probably plug this into your login filter somewhere.

  4. Peter Boling said, on August 9, 2006 at 4:03 am

    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?

  5. sausheong said, on August 9, 2006 at 11:27 am

    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.

  6. Peter Boling said, on August 15, 2006 at 10:11 pm

    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… :(

  7. sausheong said, on August 15, 2006 at 10:30 pm

    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.

  8. Daniel Schömer said, on August 29, 2006 at 6:21 pm

    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.

  9. Daniel Schömer said, on August 29, 2006 at 6:21 pm

    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.

  10. Captain’s Log » passwords, passwords said, on February 2, 2007 at 8:40 am

    […] The next step would be getting the Bridge to use the same logins, so that’s a matter of some Rails LDAP magic (I was going to think about Rails-Apache magic, but at some point I may move to an apache-mongrel-proxy type stack and I think that plays havoc when you use apache to authenticate). […]

  11. […] Ruby/Rails user authentication with Microsoft Active Directory  The comments include some talk about invisible logons which is something I would like to tackle in the near future to see if I could get it to work.  This would be the ideal situation for internal network users of the applications so they don’t have to sign in all the time, and it would force authentication from the outside user who isn’t already authenticated on the domain. […]

  12. axplains said, on June 8, 2007 at 8:47 pm

    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

  13. rajesh said, on June 29, 2007 at 8:46 pm

    i wat where to write code what to write controller,model,view plz provide

  14. Florian said, on October 5, 2007 at 1:04 am

    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!!!

  15. suresh said, on June 19, 2008 at 6:23 pm

    I was searching for an active directory authentication. Thanks it worked….

  16. John39 said, on October 23, 2009 at 6:28 am

    What the imbalance creates. ,

  17. helpdiabetics.co said, on April 3, 2014 at 3:49 am

    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.

  18. Satish said, on August 18, 2014 at 2:32 pm

    I am unable to find the gem “ldap-0.9.5-mswin32.gem”,where can i get this gem.Pls help!!!!

  19. platinum embossed non tip said, on October 19, 2014 at 9:58 am

    It’s remarkable in support of me to have a web page, which is
    good in support of my know-how. thanks admin

  20. dog supplies holiday hoodies said, on October 20, 2014 at 6:45 pm

    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!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 450 other followers

%d bloggers like this: