Class: SimpleLdapAuthenticator

Inherits:
Object
  • Object
show all
Defined in:
lib/simple_ldap_authenticator.rb

Overview

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 = ‘%[email protected]’ # 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 = Logger.new($stdout) # for logging authentication successes/failures

The class is used as a singleton, 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. = '%[email protected]'

SimpleLdapAuthenticator.valid?(username, password)
# => true or false (or raise if there is an issue connecting to the server)

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.connectionObject

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.



70
71
72
73
74
75
76
77
78
# File 'lib/simple_ldap_authenticator.rb', line 70

def connection
  return @connection if @connection
  load_ldap_library
  @connection = if ldap_library == 'net/ldap'
    Net::LDAP.new(:host=>server, :port=>(port), :encryption=>(:simple_tls if use_ssl))
  else
    (use_ssl ? LDAP::SSLConn : LDAP::Conn).new(server, port)
  end
end

.ldap_libraryObject

Returns the value of attribute ldap_library.



36
37
38
# File 'lib/simple_ldap_authenticator.rb', line 36

def ldap_library
  @ldap_library
end

.loggerObject

Returns the value of attribute logger.



36
37
38
# File 'lib/simple_ldap_authenticator.rb', line 36

def logger
  @logger
end

.login_formatObject

Returns the value of attribute login_format.



36
37
38
# File 'lib/simple_ldap_authenticator.rb', line 36

def 
  @login_format
end

.portObject

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



81
82
83
# File 'lib/simple_ldap_authenticator.rb', line 81

def port
  @port ||= use_ssl ? 636 : 389
end

.serversObject

Returns the value of attribute servers.



36
37
38
# File 'lib/simple_ldap_authenticator.rb', line 36

def servers
  @servers
end

.use_sslObject

Returns the value of attribute use_ssl.



36
37
38
# File 'lib/simple_ldap_authenticator.rb', line 36

def use_ssl
  @use_ssl
end

Class Method Details

.load_ldap_libraryObject

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



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/simple_ldap_authenticator.rb', line 40

def load_ldap_library
  return if @ldap_library_loaded
  if @ldap_library
    if @ldap_library == 'net/ldap'
      require 'net/ldap'
    else
      require 'ldap'
      require 'ldap/control'
    end
  else
    begin
      require 'ldap'
      require 'ldap/control'
      @ldap_library = 'ldap'
    rescue LoadError
      require 'net/ldap'
      @ldap_library = 'net/ldap'
    end
  end
  @ldap_library_loaded = true
end

.serverObject

The next LDAP server to which to connect



63
64
65
# File 'lib/simple_ldap_authenticator.rb', line 63

def server
  servers[0]
end

.switch_serverObject

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



87
88
89
90
# File 'lib/simple_ldap_authenticator.rb', line 87

def switch_server
  self.connection = nil
  servers << servers.shift
end

.valid?(login, password) ⇒ Boolean

Check the validity of a login/password combination

Returns:

  • (Boolean)


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/simple_ldap_authenticator.rb', line 93

def valid?(, password)
   = .to_s
  password = password.to_s
  connection = self.connection
  if password == '' || password.include?("\0") || .include?("\0")
    false
  elsif ldap_library == 'net/ldap'
    connection.authenticate( % , password)
    begin
      if connection.bind
        logger.info("Authenticated #{} by #{server}") if logger
        true
      else
        logger.info("Error attempting to authenticate #{} by #{server}: #{connection.get_operation_result.code} #{connection.get_operation_result.message}") if logger
        switch_server unless connection.get_operation_result.code == 49
        false
      end
    rescue Net::LDAP::Error, SocketError, SystemCallError => error
      logger.info("Error attempting to authenticate #{} by #{server}: #{error.message}") if logger
      switch_server
      false
    end
  else
    connection.unbind if connection.bound?
    begin
      connection.bind( % , password)
      connection.unbind
      logger.info("Authenticated #{} by #{server}") if logger
      true
    rescue LDAP::ResultError => error
      connection.unbind if connection.bound?
      logger.info("Error attempting to authenticate #{} by #{server}: #{error.message}") if logger
      switch_server unless error.message == 'Invalid credentials'
      false
    end
  end
end