LDAP through Ruby or Rails
Here is sample code I use with the net-ldap gem to verify user logins from the ActiveDirectory server at my work:
require 'net/ldap' # gem install net-ldap
def name_for_login( email, password )
email = email[/\A\w+/].downcase # Throw out the domain, if it was there
email << "@mycompany.com" # I only check people in my company
ldap = Net::LDAP.new(
host: 'ldap.mycompany.com', # Thankfully this is a standard name
auth: { method: :simple, email: email, password:password }
)
if ldap.bind
# Yay, the login credentials were valid!
# Get the user's full name and return it
ldap.search(
base: "OU=Users,OU=Accounts,DC=mycompany,DC=com",
filter: Net::LDAP::Filter.eq( "mail", email ),
attributes: %w[ displayName ],
return_result:true
).first.displayName.first
end
end
The first.displayName.first
code at the end looks a little goofy, and so might benefit from some explanation:
Net::LDAP#search
always returns an array of results, even if you end up matching only one entry. The first call tofirst
finds the first (and presumably only) entry that matched the email address.The
Net::LDAP::Entry
returned by the search conveniently lets you access attributes via method name, sosome_entry.displayName
is the same assome_entry['displayName']
.Every attribute in a
Net::LDAP::Entry
is always an array of values, even when only one value is present. Although it might be silly to have a user with multiple "displayName" values, LDAP's generic nature means that it's possible. The finalfirst
invocation turns the array-of-one-string into just the string for the user's full name.
How to Ruby on Rails authentication with LDAP?
Here's a utility class I've used in the past to do multi-server LDAP check:
require 'net/ldap'
# Ldap.authenticate('user', 'password')
# => `true` if valid
# => `false` if invalid
# => `nil` if LDAP unavailable
class Ldap
def self.config
{
domain: 'mydomain',
servers: ['server1', 'server2']
}
end
def self.authenticate(login, pass)
return false if login.empty? or pass.empty?
config['servers'].each do |server|
auth = authenticate_against_server(login, pass, server, config['domain'])
return auth unless auth.nil?
end
nil
end
private
def self.authenticate_against_server(login, pass, host, domain)
conn = Net::LDAP.new(
host: host,
port: 636,
base: "dc=#{domain}, dc=local",
encryption: :simple_tls,
auth: { username: "#{login}@#{domain}.local",
password: pass,
method: :simple }
)
Timeout::timeout(15) do
return conn.bind ? true : false
end
rescue Net::LDAP::LdapError => e
notify_ldap_admin(host, 'Error', e)
return nil
rescue Timeout::Error => e
notify_ldap_admin(host, 'Timeout', e)
return nil
end
def self.notify_ldap_admin(host, error_type, error)
msg = "LDAP #{error_type} on #{host}"
RAILS_DEFAULT_LOGGER.debug(msg)
DeveloperMailer.deliver_ldap_failure_msg(msg, error)
end
end
Using ldap to connect to ad with devise ruby on rails
Turns out my company has a different way of authorizing a user. I added the advanced flag to my devise ldap install, and set this accordingly and presto it worked.
==> Advanced LDAP Configuration
config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{login}@mydomain.com"}
I have an ldap connection on my RoR app but now how do I check users on login?
You could create a service that handles that process:
app/services/authenticate_user.rb
class AuthenticateUser
def initialize(user, password)
@user = user
@password = password
end
def call
user_is_valid?
end
private
def user_is_valid?
ldap = Net::LDAP.new
ldap.host = your_server_ip_address
ldap.port = 389
ldap.auth(@user, @password)
ldap.bind
end
end
Then use it in your controller:
class SessionsController < ApplicationController
def new
end
def create
username = params[:NumeroEmpregado]
password = params[:password]
name = "Some Name" # Change "Some Name" to set the correct name
if AuthenticateUser.new(username, password).call
user = User.create_with(nome: name).find_or_create_by(NumeroEmpregado: username)
session[:user_id] = user.id
redirect_to '/'
else
flash[:error] = "Erro! \nNúmero de Empregado e/ou password incorrecto(a)"
redirect_to '/login'
end
end
def destroy
session[:user_id] = nil
redirect_to '/index/new'
end
end
AuthenticateUser.new(user, password).call
will return true
when valid user
and password
are provided, and will return false
otherwise.
This is a basic example covering only the LDAP authentication, you will need to adapt it for your specific needs, including exception handling.
Ruby on Rails: LDAP user operations
read the documentation of the
gem(https://github.com/cschiewek/devise_ldap_authenticatable)add in initializer config/initializers/devise.rb
ldap_create_user (default: false)
If set to true, all valid LDAP users will be allowed to login
and an appropriate user record will be created. If set to false, you will
have to create the user record before they will be allowed to login.
Ruby on Rails - LDAP based authentication
Check out .bind_as
: According to the docs
http://www.rubydoc.info/gems/ruby-net-ldap/Net/LDAP#bind_as-instance_method
it is for testing authentication credentials.
Ruby with LDAP or AD
ActiveDirectory is an implementation of the LDAP. You can use the RubyLDAP gem to integrate with AD. I am currently using this gem to connect from a RHEL server to a Windows Domain Controller.
gem install ruby-ldap
Related Topics
Rails Article Helper - "A" or "An"
What Does "<Top (Required)>" Mean in a Ruby Stack Trace
Is Everything an Object in Ruby
Ruby - Send Get Request with Headers
Heroku App Crash H10 - Bash: Bin/Rails: No Such File or Directory
Converting a Hexadecimal Digest to Base64 in Ruby
Detect If Application Was Started as Http Server or Not (Rake Task, Rconsole etc)
Ruby Hash Autovivification (Facets)
Windows/Ruby/Rails Install --- .Cannot Load Such File -- SQLite3/Sqlite3_Native Windows
How to Send Message Using Gmail API with Ruby Google API Client
How to Traverse Symlinked Directories in Ruby with a "**" Glob
What Does ::Myclass Ruby Scope Operator Do