devise_ldap_authenticatable 0.8.5 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: abe0050e42cc42dc4aae30f06758c90d38ac1311
4
- data.tar.gz: 4ef05f917c2a93fe1a6c9d6f799d86e0721db43b
3
+ metadata.gz: 32d0f8a193c1b3669af1a6f2271f62a750bc2d49
4
+ data.tar.gz: afefa657196cbbccd64b415f0549d40779647427
5
5
  SHA512:
6
- metadata.gz: f279002a80b2c7853af2c2b49620b177277bff0d5eecef58bf3ceea03f2d6ef536442f08199f715f18299dfc65da1f5eed8eb6e197aeb8f95398ff8b6ad41608
7
- data.tar.gz: 984e1a040da8879d1de98896c68159d2459f043e06445fb222cb1d111eb5330711ab9115cd4c83e1333044f541e305e887bad42a5dfa4b2647c628e6833b4bec
6
+ metadata.gz: '029eeaad644b3d7026039cc535f15e0e280ad1af4a9e7af803e638c7f6861b8abd5fdf81c0ada09d4164a82fe00ab2569594b9fb06c04f18e904eadd67eb970c'
7
+ data.tar.gz: 430fd5c92a054178f1a209fba7673fb8e578b70c718b4aaf047131fdc9f591979db4bdf5d30dd2e0d2ea63b37cc231bf53d738ed363963af3353e3382000b91a
data/.gitignore CHANGED
@@ -7,4 +7,5 @@ test/ldap/openldap-data/*
7
7
  test/ldap/openldap-data/run/slapd.*
8
8
  test/rails_app/tmp
9
9
  pkg/*
10
- *.gem
10
+ *.gem
11
+ .vscode
data/README.md CHANGED
@@ -1,10 +1,5 @@
1
1
  Devise LDAP Authenticatable
2
2
  ===========================
3
-
4
- Why this fork?
5
- --------------
6
- This fork changes a few lines to allow the admin binding to be set to the user trying to log in.
7
-
8
3
  [![Gem Version](https://badge.fury.io/rb/devise_ldap_authenticatable.png)](http://badge.fury.io/rb/devise_ldap_authenticatable)
9
4
  [![Code Climate](https://codeclimate.com/github/cschiewek/devise_ldap_authenticatable.png)](https://codeclimate.com/github/cschiewek/devise_ldap_authenticatable)
10
5
  [![Dependency Status](https://gemnasium.com/cschiewek/devise_ldap_authenticatable.png)](https://gemnasium.com/cschiewek/devise_ldap_authenticatable)
@@ -15,7 +10,7 @@ If you are building applications for use within your organization which require
15
10
 
16
11
  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.
17
12
 
18
- For a screencast with an example application, please visit: [http://random-rails.blogspot.com/2010/07/ldap-authentication-with-devise.html](http://random-rails.blogspot.com/2010/07/ldap-authentication-with-devise.html)
13
+ For a screencast with an example application, please visit: [http://corrupt.net/2010/07/05/LDAP-Authentication-With-Devise/](http://corrupt.net/2010/07/05/LDAP-Authentication-With-Devise/)
19
14
 
20
15
  Prerequisites
21
16
  -------------
@@ -24,6 +19,8 @@ Prerequisites
24
19
 
25
20
  Note: Rails 3.x / Devise 2.x has been moved to the 0.7 branch. All 0.7.x gems will support Rails 3, where as 0.8.x will support Rails 4.
26
21
 
22
+ If you are transitioning from having Devise manage your users' passwords in the database to using LDAP auth, you may have to update your `users` table to make `encrypted_password` nullable, or else the LDAP user insert will fail.
23
+
27
24
  Usage
28
25
  -----
29
26
  In the Gemfile for your application:
@@ -83,7 +80,9 @@ In initializer `config/initializers/devise.rb` :
83
80
  * `ldap_check_group_membership` _(default: false)_
84
81
  * When set to true, the user trying to login will be checked to make sure they are in all of groups specified in the ldap.yml file.
85
82
  * `ldap_check_attributes` _(default: false)_
86
- * When set to true, the user trying to login will be checked to make sure they have all of the attributes in the ldap.yml file.
83
+ * When set to true, the user trying to login will be checked to make sure their attributes match those specified in the ldap.yml file.
84
+ * `ldap_check_attributes_presence` _(default: false)_
85
+ * When set to true, the user trying to login will be checked against all `require_attribute_presence` attributes in the ldap.yml file, either present _(attr: true)_,or not present _(attr: false)_.
87
86
  * `ldap_use_admin_to_bind` _(default: false)_
88
87
  * When set to true, the admin user will be used to bind to the LDAP server during authentication.
89
88
  * `ldap_check_group_membership_without_admin` _(default: false)_
@@ -116,9 +115,9 @@ Devise LDAP Authenticatable uses a running OpenLDAP server to do automated accep
116
115
 
117
116
  On OS X, this is available out of the box.
118
117
 
119
- On Ubuntu, you can install OpenLDAP with `sudo apt-get install slapd ldap-utils`. If slapd runs under AppArmor, add an exception like this to `/etc/apparmor.d/local/usr.sbin.slapd` to let slapd read our configs.
118
+ On Ubuntu, you can install OpenLDAP with `sudo apt-get install slapd ldap-utils`. If slapd runs under AppArmor, add an exception like this to `/etc/apparmor.d/local/usr.sbin.slapd` to let slapd read our configs (reload using `sudo service apparmor reload` afterwards).
120
119
 
121
- /path/to/devise_ldap_authenticatable/spec/ldap/** rw,$
120
+ /path/to/devise_ldap_authenticatable/spec/ldap/** rw,
122
121
 
123
122
  To start hacking on `devise_ldap_authentication`, clone the github repository, start the test LDAP server, and run the rake test task:
124
123
 
@@ -129,7 +128,7 @@ To start hacking on `devise_ldap_authentication`, clone the github repository, s
129
128
  # in a separate console or backgrounded
130
129
  ./spec/ldap/run-server
131
130
 
132
- bundle exec rake db:migrate # first time only
131
+ RAILS_ENV=test bundle exec rake db:migrate # first time only
133
132
  bundle exec rake spec
134
133
 
135
134
  References
@@ -18,16 +18,16 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency('devise', '>= 3.4.1')
22
- s.add_dependency('net-ldap', '>= 0.6.0', '<= 0.11')
21
+ s.add_dependency 'devise', '>= 3.4.1'
22
+ s.add_dependency 'net-ldap', '>= 0.16.0'
23
23
 
24
- s.add_development_dependency('rake', '>= 0.9')
25
- s.add_development_dependency('rdoc', '>= 3')
26
- s.add_development_dependency('rails', '>= 4.0')
27
- s.add_development_dependency('sqlite3')
28
- s.add_development_dependency('factory_girl_rails', '~> 1.0')
29
- s.add_development_dependency('factory_girl', '~> 2.0')
30
- s.add_development_dependency('rspec-rails')
24
+ s.add_development_dependency 'rake', '>= 0.9'
25
+ s.add_development_dependency 'rdoc', '>= 3'
26
+ s.add_development_dependency 'rails', '>= 4.0'
27
+ s.add_development_dependency 'sqlite3'
28
+ s.add_development_dependency 'factory_girl_rails', '~> 1.0'
29
+ s.add_development_dependency 'factory_girl', '~> 2.0'
30
+ s.add_development_dependency 'rspec-rails'
31
31
 
32
32
  %w{database_cleaner capybara launchy}.each do |dep|
33
33
  s.add_development_dependency(dep)
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  require 'devise'
3
+ require 'net/ldap'
3
4
 
4
5
  require 'devise_ldap_authenticatable/exception'
5
6
  require 'devise_ldap_authenticatable/logger'
@@ -11,31 +12,40 @@ module Devise
11
12
  # Allow logging
12
13
  mattr_accessor :ldap_logger
13
14
  @@ldap_logger = true
14
-
15
+
15
16
  # Add valid users to database
16
17
  mattr_accessor :ldap_create_user
17
18
  @@ldap_create_user = false
18
-
19
+
19
20
  # A path to YAML config file or a Proc that returns a
20
21
  # configuration hash
21
22
  mattr_accessor :ldap_config
22
23
  # @@ldap_config = "#{Rails.root}/config/ldap.yml"
23
-
24
+
24
25
  mattr_accessor :ldap_update_password
25
26
  @@ldap_update_password = true
26
-
27
+
27
28
  mattr_accessor :ldap_check_group_membership
28
29
  @@ldap_check_group_membership = false
29
-
30
+
31
+ mattr_accessor :ldap_check_group_membership_without_admin
32
+ @@ldap_check_group_membership_without_admin = false
33
+
30
34
  mattr_accessor :ldap_check_attributes
31
35
  @@ldap_check_role_attribute = false
32
-
36
+
37
+ mattr_accessor :ldap_check_attributes_presence
38
+ @@ldap_check_attributes_presence = false
39
+
33
40
  mattr_accessor :ldap_use_admin_to_bind
34
41
  @@ldap_use_admin_to_bind = false
35
-
42
+
36
43
  mattr_accessor :ldap_auth_username_builder
37
44
  @@ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }
38
45
 
46
+ mattr_accessor :ldap_auth_password_builder
47
+ @@ldap_auth_password_builder = Proc.new() {|new_password| Net::LDAP::Password.generate(:sha, new_password) }
48
+
39
49
  mattr_accessor :ldap_ad_group_check
40
50
  @@ldap_ad_group_check = false
41
51
  end
@@ -15,6 +15,16 @@ module Devise
15
15
  resource.authorized?
16
16
  end
17
17
 
18
+ def self.expired_valid_credentials?(login, password_plaintext)
19
+ options = {:login => login,
20
+ :password => password_plaintext,
21
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
22
+ :admin => ::Devise.ldap_use_admin_to_bind}
23
+
24
+ resource = Devise::LDAP::Connection.new(options)
25
+ resource.expired_valid_credentials?
26
+ end
27
+
18
28
  def self.update_password(login, new_password)
19
29
  options = {:login => login,
20
30
  :new_password => new_password,
@@ -34,7 +44,7 @@ module Devise
34
44
  :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
35
45
  :admin => ::Devise.ldap_use_admin_to_bind}
36
46
 
37
- resource = Devise::LDAP::Connection.new(options)
47
+ Devise::LDAP::Connection.new(options)
38
48
  end
39
49
 
40
50
  def self.valid_login?(login)
@@ -54,18 +64,18 @@ module Devise
54
64
  end
55
65
 
56
66
  def self.set_ldap_param(login, param, new_value, password = nil)
57
- options = { :login => login,
58
- :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
59
- :password => password }
67
+ options = {:login => login,
68
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
69
+ :password => password }
60
70
 
61
71
  resource = Devise::LDAP::Connection.new(options)
62
72
  resource.set_param(param, new_value)
63
73
  end
64
74
 
65
75
  def self.delete_ldap_param(login, param, password = nil)
66
- options = { :login => login,
67
- :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
68
- :password => password }
76
+ options = {:login => login,
77
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
78
+ :password => password }
69
79
 
70
80
  resource = Devise::LDAP::Connection.new(options)
71
81
  resource.delete_param(param)
@@ -79,9 +89,6 @@ module Devise
79
89
  def self.get_ldap_entry(login)
80
90
  self.ldap_connect(login).search_for_login
81
91
  end
82
-
83
92
  end
84
-
85
93
  end
86
-
87
94
  end
@@ -24,11 +24,13 @@ module Devise
24
24
 
25
25
  @group_base = ldap_config["group_base"]
26
26
  @check_group_membership = ldap_config.has_key?("check_group_membership") ? ldap_config["check_group_membership"] : ::Devise.ldap_check_group_membership
27
+ @check_group_membership_without_admin = ldap_config.has_key?("check_group_membership_without_admin") ? ldap_config["check_group_membership_without_admin"] : ::Devise.ldap_check_group_membership_without_admin
27
28
  @required_groups = ldap_config["required_groups"]
29
+ @group_membership_attribute = ldap_config.has_key?("group_membership_attribute") ? ldap_config["group_membership_attribute"] : "uniqueMember"
28
30
  @required_attributes = ldap_config["require_attribute"]
31
+ @required_attributes_presence = ldap_config["require_attribute_presence"]
29
32
 
30
33
  @ldap.auth ldap_config["admin_user"], ldap_config["admin_password"] if params[:admin]
31
- @ldap.auth params[:login], params[:password] if ldap_config["admin_as_user"]
32
34
 
33
35
  @login = params[:login]
34
36
  @password = params[:password]
@@ -83,10 +85,25 @@ module Devise
83
85
  authenticate!
84
86
  end
85
87
 
88
+ def last_message_bad_credentials?
89
+ @ldap.get_operation_result.error_message.to_s.include? 'AcceptSecurityContext error, data 52e'
90
+ end
91
+
92
+ def last_message_expired_credentials?
93
+ @ldap.get_operation_result.error_message.to_s.include? 'AcceptSecurityContext error, data 773'
94
+ end
95
+
86
96
  def authorized?
87
97
  DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
88
98
  if !authenticated?
89
- DeviseLdapAuthenticatable::Logger.send("Not authorized because not authenticated.")
99
+ if last_message_bad_credentials?
100
+ DeviseLdapAuthenticatable::Logger.send("Not authorized because of invalid credentials.")
101
+ elsif last_message_expired_credentials?
102
+ DeviseLdapAuthenticatable::Logger.send("Not authorized because of expired credentials.")
103
+ else
104
+ DeviseLdapAuthenticatable::Logger.send("Not authorized because not authenticated.")
105
+ end
106
+
90
107
  return false
91
108
  elsif !in_required_groups?
92
109
  DeviseLdapAuthenticatable::Logger.send("Not authorized because not in required groups.")
@@ -94,17 +111,26 @@ module Devise
94
111
  elsif !has_required_attribute?
95
112
  DeviseLdapAuthenticatable::Logger.send("Not authorized because does not have required attribute.")
96
113
  return false
114
+ elsif !has_required_attribute_presence?
115
+ DeviseLdapAuthenticatable::Logger.send("Not authorized because does not have required attribute present.")
116
+ return false
97
117
  else
98
118
  return true
99
119
  end
100
120
  end
101
121
 
122
+ def expired_valid_credentials?
123
+ DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
124
+
125
+ !authenticated? && last_message_expired_credentials?
126
+ end
127
+
102
128
  def change_password!
103
- update_ldap(:userpassword => Net::LDAP::Password.generate(:sha, @new_password))
129
+ update_ldap(:userPassword => ::Devise.ldap_auth_password_builder.call(@new_password))
104
130
  end
105
131
 
106
132
  def in_required_groups?
107
- return true unless @check_group_membership
133
+ return true unless @check_group_membership || @check_group_membership_without_admin
108
134
 
109
135
  ## FIXME set errors here, the ldap.yml isn't set properly.
110
136
  return false if @required_groups.nil?
@@ -122,23 +148,29 @@ module Devise
122
148
  def in_group?(group_name, group_attribute = LDAP::DEFAULT_GROUP_UNIQUE_MEMBER_LIST_KEY)
123
149
  in_group = false
124
150
 
125
- admin_ldap = Connection.admin
151
+ if @check_group_membership_without_admin
152
+ group_checking_ldap = @ldap
153
+ else
154
+ group_checking_ldap = Connection.admin
155
+ end
126
156
 
127
157
  unless ::Devise.ldap_ad_group_check
128
- admin_ldap.search(:base => group_name, :scope => Net::LDAP::SearchScope_BaseObject) do |entry|
158
+ group_checking_ldap.search(:base => group_name, :scope => Net::LDAP::SearchScope_BaseObject) do |entry|
129
159
  if entry[group_attribute].include? dn
130
160
  in_group = true
161
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} IS included in group: #{group_name}")
131
162
  end
132
163
  end
133
164
  else
134
165
  # AD optimization - extension will recursively check sub-groups with one query
135
166
  # "(memberof:1.2.840.113556.1.4.1941:=group_name)"
136
- search_result = admin_ldap.search(:base => dn,
167
+ search_result = group_checking_ldap.search(:base => dn,
137
168
  :filter => Net::LDAP::Filter.ex("memberof:1.2.840.113556.1.4.1941", group_name),
138
169
  :scope => Net::LDAP::SearchScope_BaseObject)
139
170
  # Will return the user entry if belongs to group otherwise nothing
140
171
  if search_result.length == 1 && search_result[0].dn.eql?(dn)
141
172
  in_group = true
173
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} IS included in group: #{group_name}")
142
174
  end
143
175
  end
144
176
 
@@ -153,11 +185,11 @@ module Devise
153
185
  return true unless ::Devise.ldap_check_attributes
154
186
 
155
187
  admin_ldap = Connection.admin
156
-
157
188
  user = find_ldap_user(admin_ldap)
158
189
 
159
190
  @required_attributes.each do |key,val|
160
- unless user[key].include? val
191
+ matching_attributes = user[key] & Array(val)
192
+ unless (matching_attributes).any?
161
193
  DeviseLdapAuthenticatable::Logger.send("User #{dn} did not match attribute #{key}:#{val}")
162
194
  return false
163
195
  end
@@ -166,11 +198,28 @@ module Devise
166
198
  return true
167
199
  end
168
200
 
201
+ def has_required_attribute_presence?
202
+ return true unless ::Devise.ldap_check_attributes_presence
203
+
204
+ user = search_for_login
205
+
206
+ @required_attributes_presence.each do |key,val|
207
+ if val && !user.attribute_names.include?(key.to_sym)
208
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} doesn't include attribute #{key}")
209
+ return false
210
+ elsif !val && user.attribute_names.include?(key.to_sym)
211
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} includes attribute #{key}")
212
+ return false
213
+ end
214
+ end
215
+
216
+ return true
217
+ end
218
+
169
219
  def user_groups
170
220
  admin_ldap = Connection.admin
171
-
172
221
  DeviseLdapAuthenticatable::Logger.send("Getting groups for #{dn}")
173
- filter = Net::LDAP::Filter.eq("uniqueMember", dn)
222
+ filter = Net::LDAP::Filter.eq(@group_membership_attribute, dn)
174
223
  admin_ldap.search(:filter => filter, :base => @group_base).collect(&:dn)
175
224
  end
176
225
 
@@ -188,6 +237,10 @@ module Devise
188
237
  ldap_entry = nil
189
238
  match_count = 0
190
239
  @ldap.search(:filter => filter) {|entry| ldap_entry = entry; match_count+=1}
240
+ op_result= @ldap.get_operation_result
241
+ if op_result.code!=0 then
242
+ DeviseLdapAuthenticatable::Logger.send("LDAP Error #{op_result.code}: #{op_result.message}")
243
+ end
191
244
  DeviseLdapAuthenticatable::Logger.send("LDAP search yielded #{match_count} matches")
192
245
  ldap_entry
193
246
  end
@@ -53,7 +53,7 @@ module Devise
53
53
  end
54
54
 
55
55
  def ldap_groups
56
- Devise::LDAP::Adapter.get_groups(login_with)
56
+ @ldap_groups ||= Devise::LDAP::Adapter.get_groups(login_with)
57
57
  end
58
58
 
59
59
  def in_ldap_group?(group_name, group_attribute = LDAP::DEFAULT_GROUP_UNIQUE_MEMBER_LIST_KEY)
@@ -10,7 +10,7 @@ module Devise
10
10
  # indicating whether the resource is not found in the database or the credentials
11
11
  # are invalid.
12
12
  def authenticate!
13
- resource = mapping.to.find_for_ldap_authentication(authentication_hash.merge(password: password))
13
+ resource = mapping.to.find_for_ldap_authentication(authentication_hash.merge(:password => password))
14
14
 
15
15
  return fail(:invalid) unless resource
16
16
 
@@ -1,3 +1,3 @@
1
1
  module DeviseLdapAuthenticatable
2
- VERSION = "0.8.5".freeze
2
+ VERSION = "0.8.6".freeze
3
3
  end
@@ -13,7 +13,7 @@ module DeviseLdapAuthenticatable
13
13
  end
14
14
 
15
15
  def create_default_devise_settings
16
- inject_into_file "config/initializers/devise.rb", default_devise_settings, :after => "Devise.setup do |config|\n"
16
+ inject_into_file "config/initializers/devise.rb", default_devise_settings, :after => "Devise.setup do |config|\n"
17
17
  end
18
18
 
19
19
  def update_user_model
@@ -28,7 +28,7 @@ module DeviseLdapAuthenticatable
28
28
 
29
29
  def default_devise_settings
30
30
  settings = <<-eof
31
- # ==> LDAP Configuration
31
+ # ==> LDAP Configuration
32
32
  # config.ldap_logger = true
33
33
  # config.ldap_create_user = false
34
34
  # config.ldap_update_password = true
@@ -36,12 +36,13 @@ module DeviseLdapAuthenticatable
36
36
  # config.ldap_check_group_membership = false
37
37
  # config.ldap_check_group_membership_without_admin = false
38
38
  # config.ldap_check_attributes = false
39
+ # config.ldap_check_attributes_presence = false
39
40
  # config.ldap_use_admin_to_bind = false
40
41
  # config.ldap_ad_group_check = false
41
42
 
42
43
  eof
43
- if options.advanced?
44
- settings << <<-eof
44
+ if options.advanced?
45
+ settings << <<-eof
45
46
  # ==> Advanced LDAP Configuration
46
47
  # config.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "\#{attribute}=\#{login},\#{ldap.base}" }
47
48
 
@@ -1,7 +1,7 @@
1
1
  ## Authorizations
2
2
  # Uncomment out the merging for each environment that you'd like to include.
3
3
  # You can also just copy and paste the tree (do not include the "authorizations") to each
4
- # environment if you need something different per enviornment.
4
+ # environment if you need something different per environment.
5
5
  authorizations: &AUTHORIZATIONS
6
6
  allow_unauthenticated_bind: false
7
7
  group_base: ou=groups,dc=test,dc=com
@@ -18,6 +18,12 @@ authorizations: &AUTHORIZATIONS
18
18
  require_attribute:
19
19
  objectClass: inetOrgPerson
20
20
  authorizationRole: postsAdmin
21
+ ## Requires config.ldap_check_attributes_presence in devise.rb to be true
22
+ ## Can have multiple attributes set to true or false to check presence, all must match all to be authorized
23
+ require_attribute_presence:
24
+ mail: true
25
+ telephoneNumber: true
26
+ serviceAccount: false
21
27
 
22
28
  ## Environment
23
29
 
@@ -7,7 +7,9 @@ authorizations: &AUTHORIZATIONS
7
7
  require_attribute:
8
8
  objectClass: inetOrgPerson
9
9
  authorizationRole: blogAdmin
10
-
10
+ require_attribute_presence:
11
+ mail: true
12
+
11
13
  test: &TEST
12
14
  host: localhost
13
15
  port: 3389
@@ -17,6 +19,6 @@ test: &TEST
17
19
  admin_password: secret
18
20
  ssl: false
19
21
  <<: *AUTHORIZATIONS
20
-
22
+
21
23
  development:
22
24
  <<: *TEST
@@ -6,9 +6,11 @@ authorizations: &AUTHORIZATIONS
6
6
  required_groups:
7
7
  - cn=admins,<%= "ou=groups,#{@base}" %>
8
8
  require_attribute:
9
- objectClass: inetOrgPerson
9
+ objectClass:
10
+ - inetOrgPerson
11
+ - organizationalPerson
10
12
  authorizationRole: blogAdmin
11
-
13
+
12
14
  test: &TEST
13
15
  host: <%= "localhost" %>
14
16
  port: 3389
@@ -18,6 +20,6 @@ test: &TEST
18
20
  admin_password: secret
19
21
  ssl: false
20
22
  <<: *AUTHORIZATIONS
21
-
23
+
22
24
  development:
23
25
  <<: *TEST
@@ -2,7 +2,6 @@ ENV["RAILS_ENV"] = "test"
2
2
 
3
3
  require File.expand_path("rails_app/config/environment.rb", File.dirname(__FILE__))
4
4
  require 'rspec/rails'
5
- require 'rspec/autorun'
6
5
  require 'factory_girl' # not sure why this is not already required
7
6
 
8
7
  # Rails 4.1 and RSpec are a bit on different pages on who should run migrations
@@ -50,6 +49,7 @@ def default_devise_settings!
50
49
  ::Devise.ldap_config = "#{Rails.root}/config/#{"ssl_" if ENV["LDAP_SSL"]}ldap.yml"
51
50
  ::Devise.ldap_check_group_membership = false
52
51
  ::Devise.ldap_check_attributes = false
52
+ ::Devise.ldap_check_attributes_presence = false
53
53
  ::Devise.ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }
54
54
  ::Devise.authentication_keys = [:email]
55
55
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Devise::LDAP::Adapter do
4
+ describe '#expired_valid_credentials?' do
5
+ before do
6
+ ::Devise.ldap_use_admin_to_bind = true
7
+ expect_any_instance_of(Devise::LDAP::Connection).to receive(:expired_valid_credentials?)
8
+ end
9
+
10
+ it 'can bind as the admin user' do
11
+ expect(Devise::LDAP::Connection).to receive(:new)
12
+ .with(hash_including(
13
+ :login => 'test.user@test.com',
14
+ :password => 'pass',
15
+ :ldap_auth_username_builder => kind_of(Proc),
16
+ :admin => true)).and_call_original
17
+
18
+ Devise::LDAP::Adapter.expired_valid_credentials?('test.user@test.com', 'pass')
19
+ end
20
+ end
21
+ end
@@ -11,4 +11,93 @@ describe 'Connection' do
11
11
  connection = Devise::LDAP::Connection.new()
12
12
  expect(connection.ldap.base).to eq('ou=testbase,dc=test,dc=com')
13
13
  end
14
+
15
+ class TestOpResult
16
+ attr_accessor :error_message
17
+ end
18
+
19
+ describe '#expired_valid_credentials?' do
20
+ let(:conn) { double(Net::LDAP).as_null_object }
21
+ let(:error) { }
22
+ let(:is_authed) { false }
23
+ before do
24
+ expect(Net::LDAP).to receive(:new).and_return(conn)
25
+ allow(conn).to receive(:get_operation_result).and_return(TestOpResult.new.tap{|r| r.error_message = error})
26
+ allow_any_instance_of(Devise::LDAP::Connection).to receive(:authenticated?).and_return(is_authed)
27
+ allow_any_instance_of(Devise::LDAP::Connection).to receive(:dn).and_return('any dn')
28
+ expect(DeviseLdapAuthenticatable::Logger).to receive(:send).with('Authorizing user any dn')
29
+ end
30
+ subject do
31
+ Devise::LDAP::Connection.new.expired_valid_credentials?
32
+ end
33
+
34
+ context do
35
+ let(:error) { 'THIS PART CAN BE ANYTHING AcceptSecurityContext error, data 773 SO CAN THIS' }
36
+ it 'is true when expired credential error is returned and not already authenticated' do
37
+ expect(subject).to be true
38
+ end
39
+ end
40
+
41
+ context do
42
+ it 'is false when expired credential error is not returned and not already authenticated' do
43
+ expect(subject).to be false
44
+ end
45
+ end
46
+
47
+ context do
48
+ let(:is_authed) { true }
49
+ it 'is false when expired credential error is not returned and already authenticated' do
50
+ expect(subject).to be false
51
+ end
52
+ end
53
+ end
54
+
55
+ describe '#authorized?' do
56
+ let(:conn) { double(Net::LDAP).as_null_object }
57
+ let(:error) { }
58
+ let(:log_message) { }
59
+ let(:is_authed) { false }
60
+ before do
61
+ expect(Net::LDAP).to receive(:new).and_return(conn)
62
+ allow(conn).to receive(:get_operation_result).and_return(TestOpResult.new.tap{|r| r.error_message = error})
63
+ allow_any_instance_of(Devise::LDAP::Connection).to receive(:authenticated?).and_return(is_authed)
64
+ allow_any_instance_of(Devise::LDAP::Connection).to receive(:dn).and_return('any dn')
65
+ expect(DeviseLdapAuthenticatable::Logger).to receive(:send).with('Authorizing user any dn')
66
+ end
67
+ subject do
68
+ Devise::LDAP::Connection.new.authorized?
69
+ end
70
+ context do
71
+ before { expect(DeviseLdapAuthenticatable::Logger).to receive(:send).with(log_message) }
72
+
73
+ context do
74
+ let(:error) { 'THIS PART CAN BE ANYTHING AcceptSecurityContext error, data 52e SO CAN THIS' }
75
+ let(:log_message) { 'Not authorized because of invalid credentials.' }
76
+ it 'is false when credential error is returned' do
77
+ expect(subject).to be false
78
+ end
79
+ end
80
+ context do
81
+ let(:error) { 'THIS PART CAN BE ANYTHING AcceptSecurityContext error, data 773 SO CAN THIS' }
82
+ let(:log_message) { 'Not authorized because of expired credentials.' }
83
+ it 'is false when expired error is returned' do
84
+ expect(subject).to be false
85
+ end
86
+ end
87
+ context do
88
+ let(:error) { 'any error' }
89
+ let(:log_message) { 'Not authorized because not authenticated.' }
90
+ it 'is false when any other error is returned' do
91
+ expect(subject).to be false
92
+ end
93
+ end
94
+ end
95
+
96
+ context do
97
+ let(:is_authed) { true }
98
+ it 'is true when already authenticated' do
99
+ expect(subject).to be true
100
+ end
101
+ end
102
+ end
14
103
  end
@@ -16,7 +16,7 @@ describe 'Users' do
16
16
  reset_ldap_server!
17
17
  end
18
18
 
19
- describe "look up and ldap user" do
19
+ describe "look up an ldap user" do
20
20
  it "should return true for a user that does exist in LDAP" do
21
21
  assert_equal true, ::Devise::LDAP::Adapter.valid_login?('example.user@test.com')
22
22
  end
@@ -48,7 +48,7 @@ describe 'Users' do
48
48
  should_be_validated @user, "secret"
49
49
  @user.password = "changed"
50
50
  @user.change_password!("secret")
51
- should_be_validated @user, "changed", "password was not changed properly on the LDAP sevrer"
51
+ should_be_validated @user, "changed", "password was not changed properly on the LDAP server"
52
52
  end
53
53
 
54
54
  it "should not allow to change password if setting is false" do
@@ -80,7 +80,7 @@ describe 'Users' do
80
80
  it "should create a user in the database" do
81
81
  @user = User.find_for_ldap_authentication(:email => "example.user@test.com", :password => "secret")
82
82
  assert_equal(User.all.size, 1)
83
- User.all.collect(&:email).should include("example.user@test.com")
83
+ expect(User.all.collect(&:email)).to include("example.user@test.com")
84
84
  assert(@user.persisted?)
85
85
  end
86
86
 
@@ -116,7 +116,7 @@ describe 'Users' do
116
116
  ::Devise.case_insensitive_keys = [:email]
117
117
 
118
118
  @user = User.find_for_ldap_authentication(:email => "EXAMPLE.user@test.com", :password => "secret")
119
- User.all.collect(&:email).should include("example.user@test.com")
119
+ expect(User.all.collect(&:email)).to include("example.user@test.com")
120
120
  end
121
121
  end
122
122
 
@@ -135,32 +135,32 @@ describe 'Users' do
135
135
  end
136
136
 
137
137
  it "should admin should have the proper groups set" do
138
- @admin.ldap_groups.should include('cn=admins,ou=groups,dc=test,dc=com')
138
+ expect(@admin.ldap_groups).to include('cn=admins,ou=groups,dc=test,dc=com')
139
139
  end
140
140
 
141
141
  it "should user should not be allowed in" do
142
142
  should_not_be_validated @user, "secret"
143
143
  end
144
144
  end
145
-
145
+
146
146
  describe "check group membership" do
147
147
  before do
148
148
  @admin = Factory.create(:admin)
149
149
  @user = Factory.create(:user)
150
150
  end
151
-
151
+
152
152
  it "should return true for admin being in the admins group" do
153
153
  assert_equal true, @admin.in_ldap_group?('cn=admins,ou=groups,dc=test,dc=com')
154
154
  end
155
-
155
+
156
156
  it "should return false for admin being in the admins group using the 'foobar' group attribute" do
157
157
  assert_equal false, @admin.in_ldap_group?('cn=admins,ou=groups,dc=test,dc=com', 'foobar')
158
158
  end
159
-
159
+
160
160
  it "should return true for user being in the users group" do
161
161
  assert_equal true, @user.in_ldap_group?('cn=users,ou=groups,dc=test,dc=com')
162
- end
163
-
162
+ end
163
+
164
164
  it "should return false for user being in the admins group" do
165
165
  assert_equal false, @user.in_ldap_group?('cn=admins,ou=groups,dc=test,dc=com')
166
166
  end
@@ -217,6 +217,26 @@ describe 'Users' do
217
217
  end
218
218
  end
219
219
 
220
+ describe "use attribute presence for authorization" do
221
+ before do
222
+ @admin = Factory.create(:admin)
223
+ @user = Factory.create(:user)
224
+ ::Devise.ldap_check_attributes_presence = true
225
+ end
226
+
227
+ after do
228
+ ::Devise.ldap_check_attributes_presence = false
229
+ end
230
+
231
+ it "should admin should not be allowed in" do
232
+ should_not_be_validated @admin, "admin_secret"
233
+ end
234
+
235
+ it "should user should be allowed in" do
236
+ should_be_validated @user, "secret"
237
+ end
238
+ end
239
+
220
240
  describe "use admin setting to bind" do
221
241
  before do
222
242
  @admin = Factory.create(:admin)
@@ -229,6 +249,19 @@ describe 'Users' do
229
249
  end
230
250
  end
231
251
 
252
+ describe 'check password expiration' do
253
+ before { allow_any_instance_of(Devise::LDAP::Connection).to receive(:authenticated?).and_return(false) }
254
+
255
+ it 'should return false for a user that has a fresh password' do
256
+ allow_any_instance_of(Devise::LDAP::Connection).to receive(:last_message_expired_credentials?).and_return(false)
257
+ assert_equal false, ::Devise::LDAP::Adapter.expired_valid_credentials?('example.user@test.com','secret')
258
+ end
259
+
260
+ it 'should return true for a user that has an expired password' do
261
+ allow_any_instance_of(Devise::LDAP::Connection).to receive(:last_message_expired_credentials?).and_return(true)
262
+ assert_equal true, ::Devise::LDAP::Adapter.expired_valid_credentials?('example.user@test.com','secret')
263
+ end
264
+ end
232
265
  end
233
266
 
234
267
  describe "use uid for login" do
@@ -259,7 +292,7 @@ describe 'Users' do
259
292
  it "should create a user in the database" do
260
293
  @user = User.find_for_ldap_authentication(:uid => "example_user", :password => "secret")
261
294
  assert_equal(User.all.size, 1)
262
- User.all.collect(&:uid).should include("example_user")
295
+ expect(User.all.collect(&:uid)).to include("example_user")
263
296
  end
264
297
 
265
298
  it "should call ldap_before_save hooks" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_ldap_authenticatable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Curtis Schiewek
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-06-19 00:00:00.000000000 Z
13
+ date: 2018-02-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: devise
@@ -32,20 +32,14 @@ dependencies:
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 0.6.0
36
- - - "<="
37
- - !ruby/object:Gem::Version
38
- version: '0.11'
35
+ version: 0.16.0
39
36
  type: :runtime
40
37
  prerelease: false
41
38
  version_requirements: !ruby/object:Gem::Requirement
42
39
  requirements:
43
40
  - - ">="
44
41
  - !ruby/object:Gem::Version
45
- version: 0.6.0
46
- - - "<="
47
- - !ruby/object:Gem::Version
48
- version: '0.11'
42
+ version: 0.16.0
49
43
  - !ruby/object:Gem::Dependency
50
44
  name: rake
51
45
  requirement: !ruby/object:Gem::Requirement
@@ -277,6 +271,7 @@ files:
277
271
  - spec/rails_app/script/rails
278
272
  - spec/spec_helper.rb
279
273
  - spec/support/factories.rb
274
+ - spec/unit/adapter_spec.rb
280
275
  - spec/unit/connection_spec.rb
281
276
  - spec/unit/user_spec.rb
282
277
  homepage: https://github.com/cschiewek/devise_ldap_authenticatable
@@ -299,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
299
294
  version: '0'
300
295
  requirements: []
301
296
  rubyforge_project:
302
- rubygems_version: 2.4.6
297
+ rubygems_version: 2.6.11
303
298
  signing_key:
304
299
  specification_version: 4
305
300
  summary: Devise extension to allow authentication via LDAP
@@ -372,5 +367,6 @@ test_files:
372
367
  - spec/rails_app/script/rails
373
368
  - spec/spec_helper.rb
374
369
  - spec/support/factories.rb
370
+ - spec/unit/adapter_spec.rb
375
371
  - spec/unit/connection_spec.rb
376
372
  - spec/unit/user_spec.rb