Class SimpleLdapAuthenticator

  1. lib/simple_ldap_authenticator.rb
Parent: Object

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

connection ()

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.

[show source]
    # 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_ldap_library ()

Load the required LDAP library, either ‘ldap’ or ‘net/ldap‘

[show source]
    # 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
port ()

The port to use. Defaults to 389 for LDAP and 636 for LDAPS.

[show source]
    # File lib/simple_ldap_authenticator.rb, line 82
82:     def port
83:       @port ||= use_ssl ? 636 : 389
84:     end
server ()

The next LDAP server to which to connect

[show source]
    # File lib/simple_ldap_authenticator.rb, line 64
64:     def server
65:       servers[0]
66:     end
switch_server ()

Disconnect from current LDAP server and use a different LDAP server on the next authentication attempt

[show source]
    # File lib/simple_ldap_authenticator.rb, line 88
88:     def switch_server
89:       self.connection = nil
90:       servers << servers.shift
91:     end
valid? (login, password)

Check the validity of a login/password combination

[show source]
     # 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