Monday, July 5, 2010

LDAP Authentication With Devise

I have been meaning to give Devise a try for quite a while. This weekend I was finally able to try it out. One of my requirements was to be able to authenticate against an LDAP server. There was a module already written to do this for Devise, but it was only for Rails 2.3.8 and I wanted to start new projects in Rails 3, so I set out to fork the project and re-write it as a Rails 3 gem.

Since this was my first experience with Devise, to write a gem, I spent a lot of time in the ruby debugger going line by line in Devise and Warden to see how things worked and why things were breaking, which usually turned out with me making a stupid mistake.

Eventually I was able to finish up, luckily I had already went through the process of creating a gem with a generator, so I was able to add some basic generators to make the setup process easier.

I made a quick screencast on how to setup a new Rails 3 application and use LDAP authentication:


There's still a lot to do, including locking, registrations, password changes, testing, making a single sign-on solution, and a lot more. Hopefully this is enough to get people up and running for now, though.

You can find it on the rails3 branch on github at: 

14 comments:

  1. Have you tried this with Active Directory? The log doesn't show anything pertinent, but it keeps taking my back to sign_in.

    Thanks!

    ReplyDelete
  2. I just started using it with AD and it seems to be working fine. I had to modify the username builder (--advanced config) but it wasn't a big deal.

    Thanks for building this plugin. It has really made it simple to get up and going with Devise is my environment.

    Later...
    Richard

    ReplyDelete
  3. I've got the basic authentication working but am currently struggling with populating data from LDAP into the user model. Upon account creation (or, preferably, upon sign in) I would like to update database fields like cn, mail, title from AD... Any suggestions?

    ReplyDelete
  4. @Richard and @James or @anyone_else ... do you mind posting what you modified to connect to AD?

    I'm able to connect to my AD using raw net/ldap calls though for I can't seem to configure devise_ldap_authenticable properly. :(

    Thanks!

    ReplyDelete
  5. Nevermind, figured it out. I'm kind of having a bit of facepalm moment now. ^_^ TGIF!

    p.s.: Thanks Dan!

    ReplyDelete
  6. can you post the solution to connect with ActiveDirectory? Im trying to resolve it but I dont see the solution.
    Thanks!!

    ReplyDelete
  7. Louis what do you think was wrong? I can't seem to get it working on my side either :(

    ReplyDelete
  8. It took me a while to get it authenticating with Active Directory, but here is what I did...

    1. In ldap.yaml I set

    attribute: sAMAccountName

    2. In devise.rb I set

    config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{attribute}=#{login}" }

    I was also able to get it working via email address by changing the ldap_auth_username_builder to:

    config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{login}" }

    That last bit just uses the email address, not mail=you@yourdomain.com, I suppose this is one area where AD differs form OpenLDAP.

    ReplyDelete
  9. I am having problem connecting to redhat directory server. I saw "invalid username or password" message. where did the ldap log go? I did not see the ldap log in rails log. I did add the config.ldap_logger=true line in devise.rb file.

    I am using rails 3 with ruby 1.9.2.

    Thanks,
    Wuke

    ReplyDelete
  10. Hi, I'm trying to make your *exact* code using rails 3.0.4, devise 1.1.2 and devise_ldap_authenticatable 0.4.6 under Ruby1.9.
    No errors at all, but I see no LDAP traffic/queries when introducing the user/pass. Instead the authentication is performed against the sqlite database (but User model does contain :ldap_authenticatable).

    Any tip? Thanks a lot.

    ReplyDelete
  11. I got this to work with an ActiveDirectory server using the following settings:

    In ldap.yml

    development:
    host: localhost
    port: 389
    attribute: mail
    base: dc=my_domain_controller
    admin_user: my_admin_username
    admin_password: "my_admin_password"
    ssl: false

    in devise.rb:

    Devise.setup do |config|
    config.ldap_use_admin_to_bind = true
    config.ldap_create_user = true
    ... rest of the file ...
    end

    Now I'm off to figure out how to use the username in stead of the email address here and in devise, and to populate my user table with values from AD...

    ReplyDelete
  12. I just tried this with the current versions of 'devise' and 'devise_ldap_authenticatable' with a test server running OpenDS. Works straight out of the box as per the demo here. Great stuff.

    ReplyDelete
  13. I got this working against Active Directory but when I try to reference current_user.login, I got blank. any help will be appreciated.

    ReplyDelete
  14. From a design standpoint, I'm stymied by the fact that, to use groups, a user has to be in _all_ specified groups. I would think that a much more common usage scenario would be that a user is required to be in one or more of a number of groups (and, of course, one would want to retrieve what group that user is in, or, rather, a list of what groups that user is in)

    ReplyDelete