Allows for easily authenticating users via LDAP (or LDAPS). If authenticating via LDAP to a server running on localhost, you should only have to configure the login_format.
Can be configured using the following accessors (with examples):
- login_format = ’%s@domain.com’ # Active Directory, OR
- login_format = ‘cn=%s,cn=users,o=organization,c=us’ # Other LDAP servers
- servers = [‘dc1.domain.com’, ‘dc2.domain.com’] # names/addresses of LDAP servers to use
- use_ssl = true # for logging in via LDAPS
- port = 3289 # instead of 389 for LDAP or 636 for LDAPS
- logger = RAILS_DEFAULT_LOGGER # for logging authentication successes/failures
The class is used as a global variable, you are not supposed to create an instance of it. For example:
require 'simple_ldap_authenticator'
SimpleLdapAuthenticator.servers = %w'dc1.domain.com dc2.domain.com'
SimpleLdapAuthenticator.use_ssl = true
SimpleLdapAuthenticator.login_format = '%s@domain.com'
SimpleLdapAuthenticator.logger = RAILS_DEFAULT_LOGGER
class LoginController < ApplicationController
def login
return redirect_to(:action=>'try_again') unless SimpleLdapAuthenticator.valid?(params[:username], params[:password])
session[:username] = params[:username]
end
end
Attributes
| connection | [RW] | |
| ldap_library | [RW] | |
| logger | [RW] | |
| login_format | [RW] | |
| port | [RW] | |
| servers | [RW] | |
| use_ssl | [RW] |
Public class methods
The connection to the LDAP server. A single connection is made and the connection is only changed if a server returns an error other than invalid password.
# File lib/simple_ldap_authenticator.rb, line 71 71: def connection 72: return @connection if @connection 73: load_ldap_library 74: @connection = if ldap_library == 'net/ldap' 75: Net::LDAP.new(:host=>server, :port=>(port), :encryption=>(:simple_tls if use_ssl)) 76: else 77: (use_ssl ? LDAP::SSLConn : LDAP::Conn).new(server, port) 78: end 79: end
Load the required LDAP library, either ‘ldap’ or ‘net/ldap‘
# File lib/simple_ldap_authenticator.rb, line 41 41: def load_ldap_library 42: return if @ldap_library_loaded 43: if ldap_library 44: if ldap_library == 'net/ldap' 45: require 'net/ldap' 46: else 47: require 'ldap' 48: require 'ldap/control' 49: end 50: else 51: begin 52: require 'ldap' 53: require 'ldap/control' 54: ldap_library = 'ldap' 55: rescue LoadError 56: require 'net/ldap' 57: ldap_library = 'net/ldap' 58: end 59: end 60: @ldap_library_loaded = true 61: end
The port to use. Defaults to 389 for LDAP and 636 for LDAPS.
# File lib/simple_ldap_authenticator.rb, line 82 82: def port 83: @port ||= use_ssl ? 636 : 389 84: end
The next LDAP server to which to connect
# File lib/simple_ldap_authenticator.rb, line 64 64: def server 65: servers[0] 66: end
Disconnect from current LDAP server and use a different LDAP server on the next authentication attempt
# File lib/simple_ldap_authenticator.rb, line 88 88: def switch_server 89: self.connection = nil 90: servers << servers.shift 91: end
Check the validity of a login/password combination
# File lib/simple_ldap_authenticator.rb, line 94 94: def valid?(login, password) 95: if ldap_library == 'net/ldap' 96: connection.authenticate(login_format % login.to_s, password.to_s) 97: begin 98: if connection.bind 99: logger.info("Authenticated #{login.to_s} by #{server}") if logger 100: true 101: else 102: logger.info("Error attempting to authenticate #{login.to_s} by #{server}: #{connection.get_operation_result.code} #{connection.get_operation_result.message}") if logger 103: switch_server unless connection.get_operation_result.code == 49 104: false 105: end 106: rescue Net::LDAP::LdapError => error 107: logger.info("Error attempting to authenticate #{login.to_s} by #{server}: #{error.message}") if logger 108: switch_server 109: false 110: end 111: else 112: connection.unbind if connection.bound? 113: begin 114: connection.bind(login_format % login.to_s, password.to_s) 115: connection.unbind 116: logger.info("Authenticated #{login.to_s} by #{server}") if logger 117: true 118: rescue LDAP::ResultError => error 119: connection.unbind if connection.bound? 120: logger.info("Error attempting to authenticate #{login.to_s} by #{server}: #{error.message}") if logger 121: switch_server unless error.message == 'Invalid credentials' 122: false 123: end 124: end 125: end