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 = 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. = '%[email protected]'
SimpleLdapAuthenticator.logger = RAILS_DEFAULT_LOGGER
class LoginController < ApplicationController 
  def 
    return redirect_to(:action=>'try_again') unless SimpleLdapAuthenticator.valid?(params[:username], params[:password])
    session[:username] = params[:username]
  end
end

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.



71
72
73
# File 'lib/simple_ldap_authenticator.rb', line 71

def connection
  @connection
end

.ldap_libraryObject

Returns the value of attribute ldap_library.



38
39
40
# File 'lib/simple_ldap_authenticator.rb', line 38

def ldap_library
  @ldap_library
end

.loggerObject

Returns the value of attribute logger.



38
39
40
# File 'lib/simple_ldap_authenticator.rb', line 38

def logger
  @logger
end

.login_formatObject

Returns the value of attribute login_format.



38
39
40
# File 'lib/simple_ldap_authenticator.rb', line 38

def 
  @login_format
end

.portObject

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



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

def port
  @port
end

.serversObject

Returns the value of attribute servers.



38
39
40
# File 'lib/simple_ldap_authenticator.rb', line 38

def servers
  @servers
end

.use_sslObject

Returns the value of attribute use_ssl.



38
39
40
# File 'lib/simple_ldap_authenticator.rb', line 38

def use_ssl
  @use_ssl
end

Class Method Details

.load_ldap_libraryObject

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



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

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



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

def server
  servers[0]
end

.switch_serverObject

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



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

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

.valid?(login, password) ⇒ Boolean

Check the validity of a login/password combination



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
# File 'lib/simple_ldap_authenticator.rb', line 94

def valid?(, password)
  if password.to_s == ''
    false
  elsif ldap_library == 'net/ldap'
    connection.authenticate( % .to_s, password.to_s)
    begin
      if connection.bind
          logger.info("Authenticated #{.to_s} by #{server}") if logger
          true
        else
          logger.info("Error attempting to authenticate #{.to_s} 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::LdapError => error
      logger.info("Error attempting to authenticate #{.to_s} by #{server}: #{error.message}") if logger
      switch_server
      false
    end
  else
    connection.unbind if connection.bound?
    begin
      connection.bind( % .to_s, password.to_s)
      connection.unbind
      logger.info("Authenticated #{.to_s} by #{server}") if logger
      true
    rescue LDAP::ResultError => error
      connection.unbind if connection.bound?
      logger.info("Error attempting to authenticate #{.to_s} by #{server}: #{error.message}") if logger
      switch_server unless error.message == 'Invalid credentials'
      false
    end
  end
end