Reputation: 165
I'm currently working on a rails project in which I am in charge of user authentication. We've decided to use third party authentication and I tried following an example setup. The example is done by Kevin Thompson and is called example.
According to the LDAP sever's documentation, the steps I need to do are:
I've followed Thompson's example, except that I'm not using nifty; using devise for user management and omniauth-ldap for authentication. However, it's not quite working, and I'm wondering if it has to do with a discrepancy between what the server documentation tells me to do and what omniauth-ldap is actually doing...
Specifically, my problem is that I always get an "Invalid credentials" error. Is this because of a mismatch between what I need to do and what omniauth-ldap is doing?
Advice or suggestions are greatly appreciated!
A little more information about how I've set up (to maintain anonymity, I replaced some things) I can post more of my code upon request.
config/initializers/devise.rb:
config.omniauth :ldap,
:host => 'ldap1.its.domain.ext',
:base => 'ou=People, dc=domain, dc=ext',
:port => 389,
:attrs => 'uid',
:method => :plain,
:uid => 'uid'
app/controllers/users/omniauth_callbacks_controller.rb:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_filter :verify_authenticity_token
def ldap
ldap_return = request.env["omniauth.auth"]["extra"]["raw_info"]
username = ldap_return.uid[0].to_s
if @user = User.find_by_username(username)
sign_in_and_redirect @user
else
@user = User.create(:username => username,)
sign_in_and_redirect @user
end
end
end
Upvotes: 3
Views: 4367
Reputation: 6042
I can't add this as a comment, as I don't have 50 reputation yet, however I found this which may be of use to some people here.
http://blackfistsecurity.blogspot.com.au/2011/12/rails-authentication-using-devise-and.html
I was originally trying to use Omniauth and Omniauth-LDAP without anything else, but the lack of documentation on omniauth-ldap's part makes things difficult.
edit:
Instead of using Omniauth-LDAP, I ended up opting for a vanilla devise install, and wrote my own LDAP functionality. Please note: I use mongoid, and as such the code below is directed towards MongoDB. It can be easily modified for ActiveRecord, however.
In order to do this, I edited the new
action in the sessions
controller, similarly to as follows:
ldap = Net::LDAP.new
ldap.host = 'domainOrIP'
ldap.port = 389
ldap.auth 'user', 'password'
if ldap.bind
# success, so let's check if the user exists
@existing_user = User.where({username: params[:user][:username] }).first
if @existing_user == nil
#create the user
@user = User.new( {username: params[:user][:username], password: ''})
# I didn't personally store the user's password, as I use LDAP for authentication. (If you save this, please hash and salt it first!!)
@user.save
flash[:notice] = "Success!"
redirect_to '/'
else # already existed
@user = User.find({ username: params[:user][:username] })
flash[:notice] = "Success!"
redirect_to '/'
end
else
flash[:danger] = "An error occurred whilst authenticating with your LDAP server. Please check the configuration and try again."
redirect_to '/'
end
I then left Devise to handle everything else. Worked brilliantly for me -- the code above is from memory, however, so may not be 100% accurate. :)
edit 2: More information on how to use the Net::LDAP class can be found here: http://www.rubydoc.info/gems/ruby-net-ldap/Net/LDAP
Upvotes: 0
Reputation: 104
I just solved a similar issue.
First, you'll need to determine if your domain allows anonymous binding. This was not allowed in my case. There is an great pull request for using the current user to bind, dorren/omniauth-ldap. Otherwise, you'll need a system account. Just to get moving initially, I used my username(i.e., userPrincipalName)/password for :bind_dn and :password.
Secondly, for LDAP authentication, the two uid values that are used to authenticate are sAMAccountName(username) or userPrincipalName([email protected]). I found that my system uses userPrincipalName. To prevent the user from entering that in, I just concatenated the domain prior to submitting the form.
Try this config.
config.omniauth :ldap,
:host => 'ldap.domain.ext',
:base => 'dc=ldap, dc=domain, dc=ext',
:port => 389,
:method => :plain,
:uid => 'userPrincipalName',
:bind_dn => 'bind_dn',
:password => 'password'
I believe :bind_dn can be of the form:
'CN=LastName\, FirstName, OU=People, DC=ldap, DC=domain, DC=ext'
OR
I also found writing a ruby script using Net::LDAP, to bind and search really helped me learn about Active Directory as well, since I had no knowledge of this subject prior to this task.
Upvotes: 5