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
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.
Rails authentication with LDAP and local database
Ruby's Net::LDAP library is pretty good.
Here's a simplified version of what I've been using for years:
# sessions_controller.rb
def create
user = User.find_by_login(params[:login])
if user && Ldap.authenticate(params[:login], params[:password])
self.current_user = user
Rails.logger.info "Logged in #{user.name}"
flash[:notice] = "Successfully Logged In!"
redirect_back_or_default root_url
else
flash[:alert] = "Invalid User credentials"
render :new
end
end
# lib/ldap.rb
# Ldap.authenticate('user','password')
# Returns true if validated
# Returns false if invalidated
# Returns nil if LDAP unavailable
require 'net/ldap'
class Ldap
def self.config
# this is actually loaded from a yaml config file
{
:domain => 'YOURDOMAIN',
:host => '10.10.10.100'
}
end
def self.authenticate(login, password)
conn = Net::LDAP.new(
:host => config[:host],
:port => 636,
:base => "dc=#{config[:domain]}, dc=local",
:encryption => :simple_tls,
:auth => {
:username => "#{login}@#{config[:domain]}.local",
:password => password,
:method => :simple
}
)
Timeout::timeout(15) do
return conn.bind ? true : false
end
rescue Net::LDAP::LdapError => e
notify_ldap_admin(config[:host],'Error',e)
nil
rescue Timeout::Error => e
notify_ldap_admin(config[:host],'Timeout',e)
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
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.
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.
Net/LDAP gem and basic auth in Rails 4 app
Have you looked at the Gem devise_ldap_authenticatable.I guess it better suits your requirement.Instead of using your own authentication system, you could use LDAP(Active directory) as an authentication provider.
If you are building applications for use within your organization
which require authentication and you want to use LDAP, this plugin is
for you.Devise LDAP Authenticatable works in replacement of Database
Authenticatable. This devise plugin has not been tested with
DatabaseAuthenticatable enabled at the same time. This is meant as a
drop in replacement for DatabaseAuthenticatable allowing for a semi
single sign on approach.
SAML based single sign on is also popularly renowned way of transmitting authentication and authorization information as an XML
. Service Provider(You) can leverage Identity Provider(Active directory- perhaps ADFS) for authentication purposes. Ruby-SAML by onelogin is well known gem for SAML implementation.
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"}
Related Topics
How to Submit Polymorphic Comments on Feed? [Error]
Rails: Convert Utc Datetime to Another Time Zone
Measure and Benchmark Time for Ruby Methods
Rails Mapping Array of Hashes Onto Single Hash
How to Select Option in Drop Down Using Capybara
How to Find the Path a Ruby Gem Is Installed at (I.E. Gem.Lib_Path C.F. Gem.Bin_Path)
Detect Number of Cpus Installed
How to Get All Class Names in a Namespace in Ruby
Ruby Shoes Gui: Continually Updating Paragraphs
Convert String to Symbol-Able in Ruby
Rails 4: How to Reset Test Database
If String Is Empty Then Return Some Default Value
Return Two and More Values from a Method
Split Ruby Regex Over Multiple Lines
How to Get Constants Defined by Ruby's Module Class via Reflection