devise_ldap_authenticatable 0.8.1 → 0.8.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -1
- data/README.md +36 -32
- data/devise_ldap_authenticatable.gemspec +9 -9
- data/lib/devise_ldap_authenticatable.rb +20 -8
- data/lib/devise_ldap_authenticatable/ldap/adapter.rb +19 -12
- data/lib/devise_ldap_authenticatable/ldap/connection.rb +94 -28
- data/lib/devise_ldap_authenticatable/model.rb +28 -24
- data/lib/devise_ldap_authenticatable/strategy.rb +25 -4
- data/lib/devise_ldap_authenticatable/version.rb +2 -2
- data/lib/generators/devise_ldap_authenticatable/install_generator.rb +19 -17
- data/lib/generators/devise_ldap_authenticatable/templates/ldap.yml +8 -1
- data/spec/rails_app/config/initializers/devise.rb +5 -0
- data/spec/rails_app/config/ldap.yml +4 -2
- data/spec/rails_app/config/ldap_with_erb.yml +5 -3
- data/spec/rails_app/config/locales/devise.en.yml +1 -0
- data/spec/rails_app/db/migrate/20100708120448_devise_create_users.rb +1 -1
- data/spec/rails_app/db/schema.rb +12 -14
- data/spec/spec_helper.rb +9 -1
- data/spec/unit/adapter_spec.rb +21 -0
- data/spec/unit/connection_spec.rb +121 -0
- data/spec/unit/user_spec.rb +91 -30
- metadata +36 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7044550949ddebd6ea7cc11cf8ed2256b892f2c27dd2fc316a7c5a2b4bdcf685
|
4
|
+
data.tar.gz: ba36af309f585a37a6e2775810b62bc95a4c5d4203e9b2f7d174418c20a39e07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d076e9ed84c61fc77dfd9f7006b594a2c841a600491d3b0c92d5bde42832b4df3324ebbb6df447221078f3d0dd5b91540d2882cec2c1e9d41bc5c84117a019e6
|
7
|
+
data.tar.gz: 9f2f642e37bf8a51db04a01aa58d93f96ceea8daf91ef7b0af3e0357c5289962c4e583aef57fb10a1f496b55d54012176b42086a3e417e482932733ace47b40f
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Devise LDAP Authenticatable
|
2
2
|
===========================
|
3
|
-
|
4
|
-
[![
|
5
|
-
[![
|
3
|
+
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/devise_ldap_authenticatable.svg)](http://badge.fury.io/rb/devise_ldap_authenticatable)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/cschiewek/devise_ldap_authenticatable.svg)](https://codeclimate.com/github/cschiewek/devise_ldap_authenticatable)
|
6
6
|
|
7
7
|
Devise LDAP Authenticatable is a LDAP based authentication strategy for the [Devise](http://github.com/plataformatec/devise) authentication framework.
|
8
8
|
|
@@ -10,25 +10,29 @@ If you are building applications for use within your organization which require
|
|
10
10
|
|
11
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.
|
12
12
|
|
13
|
-
For a screencast with an example application, please visit: [http://
|
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/)
|
14
14
|
|
15
15
|
Prerequisites
|
16
16
|
-------------
|
17
17
|
* devise ~> 3.0.0 (which requires rails ~> 4.0)
|
18
|
-
* net-ldap ~> 0.
|
18
|
+
* net-ldap ~> 0.6.0
|
19
19
|
|
20
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.
|
21
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
|
+
|
22
24
|
Usage
|
23
25
|
-----
|
24
26
|
In the Gemfile for your application:
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
```ruby
|
29
|
+
gem "devise_ldap_authenticatable"
|
30
|
+
```
|
28
31
|
To get the latest version, pull directly from github instead of the gem:
|
29
32
|
|
30
|
-
|
31
|
-
|
33
|
+
```ruby
|
34
|
+
gem "devise_ldap_authenticatable", :git => "git://github.com/cschiewek/devise_ldap_authenticatable.git"
|
35
|
+
```
|
32
36
|
|
33
37
|
Setup
|
34
38
|
-----
|
@@ -41,7 +45,7 @@ Run the rails generator for `devise_ldap_authenticatable`
|
|
41
45
|
|
42
46
|
rails generate devise_ldap_authenticatable:install [options]
|
43
47
|
|
44
|
-
This will install the
|
48
|
+
This will install the ldap.yml, update the devise.rb initializer, and update your user model. There are some options you can pass to it:
|
45
49
|
|
46
50
|
Options:
|
47
51
|
|
@@ -57,13 +61,13 @@ Querying LDAP
|
|
57
61
|
-------------
|
58
62
|
Given that `ldap_create_user` is set to true and you are authenticating with username, you can query an LDAP server for other attributes.
|
59
63
|
|
60
|
-
in your user model:
|
61
|
-
|
62
|
-
before_save :get_ldap_email
|
64
|
+
in your user model you have to simply define `ldap_before_save` method:
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
|
66
|
+
```ruby
|
67
|
+
def ldap_before_save
|
68
|
+
self.email = Devise::LDAP::Adapter.get_ldap_param(self.username,"mail").first
|
69
|
+
end
|
70
|
+
```
|
67
71
|
|
68
72
|
Configuration
|
69
73
|
-------------
|
@@ -71,25 +75,22 @@ In initializer `config/initializers/devise.rb` :
|
|
71
75
|
|
72
76
|
* `ldap_logger` _(default: true)_
|
73
77
|
* If set to true, will log LDAP queries to the Rails logger.
|
74
|
-
|
75
78
|
* `ldap_create_user` _(default: false)_
|
76
|
-
* If set to true, all valid LDAP users will be allowed to login and an appropriate user record will be created.
|
77
|
-
If set to false, you will have to create the user record before they will be allowed to login.
|
78
|
-
|
79
|
+
* If set to true, all valid LDAP users will be allowed to login and an appropriate user record will be created. If set to false, you will have to create the user record before they will be allowed to login.
|
79
80
|
* `ldap_config` _(default: #{Rails.root}/config/ldap.yml)_
|
80
|
-
|
81
|
-
|
81
|
+
* Where to find the LDAP config file. Commented out to use the default, change if needed.
|
82
82
|
* `ldap_update_password` _(default: true)_
|
83
83
|
* When doing password resets, if true will update the LDAP server. Requires admin password in the ldap.yml
|
84
|
-
|
85
84
|
* `ldap_check_group_membership` _(default: false)_
|
86
85
|
* 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.
|
87
|
-
|
88
86
|
* `ldap_check_attributes` _(default: false)_
|
89
|
-
* When set to true, the user trying to login will be checked to make sure
|
90
|
-
|
87
|
+
* 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.
|
88
|
+
* `ldap_check_attributes_presence` _(default: false)_
|
89
|
+
* 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)_.
|
91
90
|
* `ldap_use_admin_to_bind` _(default: false)_
|
92
91
|
* When set to true, the admin user will be used to bind to the LDAP server during authentication.
|
92
|
+
* `ldap_check_group_membership_without_admin` _(default: false)_
|
93
|
+
* When set to true, the group membership check is done with the user's own credentials rather than with admin credentials. Since these credentials are only available to the Devise user model during the login flow, the group check function will not work if a group check is performed when this option is true outside of the login flow (e.g., before particular actions).
|
93
94
|
|
94
95
|
Advanced Configuration
|
95
96
|
----------------------
|
@@ -97,10 +98,12 @@ These parameters will be added to `config/initializers/devise.rb` when you pass
|
|
97
98
|
|
98
99
|
* `ldap_auth_username_builder` _(default: `Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }`)_
|
99
100
|
* You can pass a proc to the username option to explicitly specify the format that you search for a users' DN on your LDAP server.
|
101
|
+
* `ldap_auth_password_build` _(default: `Proc.new() {|new_password| Net::LDAP::Password.generate(:sha, new_password) }`)_
|
102
|
+
* Optionally you can define a proc to create custom password encrption when user reset password
|
100
103
|
|
101
104
|
Troubleshooting
|
102
105
|
--------------
|
103
|
-
**Using a "username" instead of an "email":** The field that is used for logins is the first key that's configured in the `config/devise.rb` file under `config.authentication_keys`, which by default is email. For help changing this, please see the [Railscast](http://railscasts.com/episodes/210-customizing-devise) that goes through how to customize Devise.
|
106
|
+
**Using a "username" instead of an "email":** The field that is used for logins is the first key that's configured in the `config/initializers/devise.rb` file under `config.authentication_keys`, which by default is email. For help changing this, please see the [Railscast](http://railscasts.com/episodes/210-customizing-devise) that goes through how to customize Devise. Also, this [documentation](https://github.com/plataformatec/devise/wiki/How-To%3a-Allow-users-to-sign-in-using-their-username-or-email-address) from Devise can be very helpful.
|
104
107
|
|
105
108
|
**SSL certificate invalid:** If you're using a test LDAP server running a self-signed SSL certificate, make sure the appropriate root certificate is installed on your system. Alternately, you may temporarily disable certificate checking for SSL by modifying your system LDAP configuration (e.g., `/etc/openldap/ldap.conf` or `/etc/ldap/ldap.conf`) to read `TLS_REQCERT never`.
|
106
109
|
|
@@ -111,13 +114,14 @@ For additional support, questions or discussions, please see the discussion foru
|
|
111
114
|
|
112
115
|
Development guide
|
113
116
|
------------
|
114
|
-
To contribute to `devise_ldap_authentication`, you should be able to run a test OpenLDAP server. Specifically, you need the `slapd`, `ldapadd`, and `ldapmodify` binaries.
|
115
117
|
|
116
|
-
|
118
|
+
Devise LDAP Authenticatable uses a running OpenLDAP server to do automated acceptance tests. You'll need the executables `slapd`, `ldapadd`, and `ldapmodify`.
|
119
|
+
|
120
|
+
On OS X, this is available out of the box.
|
117
121
|
|
118
|
-
On Ubuntu
|
122
|
+
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).
|
119
123
|
|
120
|
-
/path/to/devise_ldap_authenticatable/spec/ldap/** rw
|
124
|
+
/path/to/devise_ldap_authenticatable/spec/ldap/** rw,
|
121
125
|
|
122
126
|
To start hacking on `devise_ldap_authentication`, clone the github repository, start the test LDAP server, and run the rake test task:
|
123
127
|
|
@@ -128,7 +132,7 @@ To start hacking on `devise_ldap_authentication`, clone the github repository, s
|
|
128
132
|
# in a separate console or backgrounded
|
129
133
|
./spec/ldap/run-server
|
130
134
|
|
131
|
-
bundle exec rake db:migrate # first time only
|
135
|
+
RAILS_ENV=test bundle exec rake db:migrate # first time only
|
132
136
|
bundle exec rake spec
|
133
137
|
|
134
138
|
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
|
22
|
-
s.add_dependency
|
21
|
+
s.add_dependency 'devise', '>= 3.4.1'
|
22
|
+
s.add_dependency 'net-ldap', '>= 0.16.0'
|
23
23
|
|
24
|
-
s.add_development_dependency
|
25
|
-
s.add_development_dependency
|
26
|
-
s.add_development_dependency
|
27
|
-
s.add_development_dependency
|
28
|
-
s.add_development_dependency
|
29
|
-
s.add_development_dependency
|
30
|
-
s.add_development_dependency
|
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,29 +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
|
+
|
20
|
+
# A path to YAML config file or a Proc that returns a
|
21
|
+
# configuration hash
|
19
22
|
mattr_accessor :ldap_config
|
20
23
|
# @@ldap_config = "#{Rails.root}/config/ldap.yml"
|
21
|
-
|
24
|
+
|
22
25
|
mattr_accessor :ldap_update_password
|
23
26
|
@@ldap_update_password = true
|
24
|
-
|
27
|
+
|
25
28
|
mattr_accessor :ldap_check_group_membership
|
26
29
|
@@ldap_check_group_membership = false
|
27
|
-
|
30
|
+
|
31
|
+
mattr_accessor :ldap_check_group_membership_without_admin
|
32
|
+
@@ldap_check_group_membership_without_admin = false
|
33
|
+
|
28
34
|
mattr_accessor :ldap_check_attributes
|
29
35
|
@@ldap_check_role_attribute = false
|
30
|
-
|
36
|
+
|
37
|
+
mattr_accessor :ldap_check_attributes_presence
|
38
|
+
@@ldap_check_attributes_presence = false
|
39
|
+
|
31
40
|
mattr_accessor :ldap_use_admin_to_bind
|
32
41
|
@@ldap_use_admin_to_bind = false
|
33
|
-
|
42
|
+
|
34
43
|
mattr_accessor :ldap_auth_username_builder
|
35
44
|
@@ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }
|
36
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
|
+
|
37
49
|
mattr_accessor :ldap_ad_group_check
|
38
50
|
@@ldap_ad_group_check = false
|
39
51
|
end
|
@@ -44,4 +56,4 @@ Devise.add_module(:ldap_authenticatable,
|
|
44
56
|
:route => :session, ## This will add the routes, rather than in the routes.rb
|
45
57
|
:strategy => true,
|
46
58
|
:controller => :sessions,
|
47
|
-
:model => 'devise_ldap_authenticatable/model')
|
59
|
+
:model => 'devise_ldap_authenticatable/model')
|
@@ -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,
|
@@ -26,7 +36,7 @@ module Devise
|
|
26
36
|
end
|
27
37
|
|
28
38
|
def self.update_own_password(login, new_password, current_password)
|
29
|
-
set_ldap_param(login, :
|
39
|
+
set_ldap_param(login, :userPassword, ::Devise.ldap_auth_password_builder.call(new_password), current_password)
|
30
40
|
end
|
31
41
|
|
32
42
|
def self.ldap_connect(login)
|
@@ -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
|
-
|
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 = {
|
58
|
-
|
59
|
-
|
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 = {
|
67
|
-
|
68
|
-
|
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
|
-
end
|
94
|
+
end
|
@@ -4,22 +4,34 @@ module Devise
|
|
4
4
|
attr_reader :ldap, :login
|
5
5
|
|
6
6
|
def initialize(params = {})
|
7
|
-
|
7
|
+
if ::Devise.ldap_config.is_a?(Proc)
|
8
|
+
ldap_config = ::Devise.ldap_config.call
|
9
|
+
else
|
10
|
+
ldap_config = YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env]
|
11
|
+
end
|
8
12
|
ldap_options = params
|
13
|
+
|
14
|
+
# Allow `ssl: true` shorthand in YAML, but enable more control with `encryption`
|
9
15
|
ldap_config["ssl"] = :simple_tls if ldap_config["ssl"] === true
|
10
16
|
ldap_options[:encryption] = ldap_config["ssl"].to_sym if ldap_config["ssl"]
|
17
|
+
ldap_options[:encryption] = ldap_config["encryption"] if ldap_config["encryption"]
|
11
18
|
|
12
19
|
@ldap = Net::LDAP.new(ldap_options)
|
13
20
|
@ldap.host = ldap_config["host"]
|
14
21
|
@ldap.port = ldap_config["port"]
|
15
22
|
@ldap.base = ldap_config["base"]
|
16
23
|
@attribute = ldap_config["attribute"]
|
24
|
+
@allow_unauthenticated_bind = ldap_config["allow_unauthenticated_bind"]
|
25
|
+
|
17
26
|
@ldap_auth_username_builder = params[:ldap_auth_username_builder]
|
18
27
|
|
19
28
|
@group_base = ldap_config["group_base"]
|
20
29
|
@check_group_membership = ldap_config.has_key?("check_group_membership") ? ldap_config["check_group_membership"] : ::Devise.ldap_check_group_membership
|
30
|
+
@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
|
21
31
|
@required_groups = ldap_config["required_groups"]
|
32
|
+
@group_membership_attribute = ldap_config.has_key?("group_membership_attribute") ? ldap_config["group_membership_attribute"] : "uniqueMember"
|
22
33
|
@required_attributes = ldap_config["require_attribute"]
|
34
|
+
@required_attributes_presence = ldap_config["require_attribute_presence"]
|
23
35
|
|
24
36
|
@ldap.auth ldap_config["admin_user"], ldap_config["admin_password"] if params[:admin]
|
25
37
|
|
@@ -37,19 +49,19 @@ module Devise
|
|
37
49
|
end
|
38
50
|
|
39
51
|
def dn
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
52
|
+
@dn ||= begin
|
53
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP dn lookup: #{@attribute}=#{@login}")
|
54
|
+
ldap_entry = search_for_login
|
55
|
+
if ldap_entry.nil?
|
56
|
+
@ldap_auth_username_builder.call(@attribute,@login,@ldap)
|
57
|
+
else
|
58
|
+
ldap_entry.dn
|
59
|
+
end
|
46
60
|
end
|
47
61
|
end
|
48
62
|
|
49
63
|
def ldap_param_value(param)
|
50
|
-
|
51
|
-
ldap_entry = nil
|
52
|
-
@ldap.search(:filter => filter) {|entry| ldap_entry = entry}
|
64
|
+
ldap_entry = search_for_login
|
53
65
|
|
54
66
|
if ldap_entry
|
55
67
|
unless ldap_entry[param].empty?
|
@@ -67,6 +79,7 @@ module Devise
|
|
67
79
|
end
|
68
80
|
|
69
81
|
def authenticate!
|
82
|
+
return false unless (@password.present? || @allow_unauthenticated_bind)
|
70
83
|
@ldap.auth(dn, @password)
|
71
84
|
@ldap.bind
|
72
85
|
end
|
@@ -75,10 +88,25 @@ module Devise
|
|
75
88
|
authenticate!
|
76
89
|
end
|
77
90
|
|
91
|
+
def last_message_bad_credentials?
|
92
|
+
@ldap.get_operation_result.error_message.to_s.include? 'AcceptSecurityContext error, data 52e'
|
93
|
+
end
|
94
|
+
|
95
|
+
def last_message_expired_credentials?
|
96
|
+
@ldap.get_operation_result.error_message.to_s.include? 'AcceptSecurityContext error, data 773'
|
97
|
+
end
|
98
|
+
|
78
99
|
def authorized?
|
79
100
|
DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
|
80
101
|
if !authenticated?
|
81
|
-
|
102
|
+
if last_message_bad_credentials?
|
103
|
+
DeviseLdapAuthenticatable::Logger.send("Not authorized because of invalid credentials.")
|
104
|
+
elsif last_message_expired_credentials?
|
105
|
+
DeviseLdapAuthenticatable::Logger.send("Not authorized because of expired credentials.")
|
106
|
+
else
|
107
|
+
DeviseLdapAuthenticatable::Logger.send("Not authorized because not authenticated.")
|
108
|
+
end
|
109
|
+
|
82
110
|
return false
|
83
111
|
elsif !in_required_groups?
|
84
112
|
DeviseLdapAuthenticatable::Logger.send("Not authorized because not in required groups.")
|
@@ -86,17 +114,26 @@ module Devise
|
|
86
114
|
elsif !has_required_attribute?
|
87
115
|
DeviseLdapAuthenticatable::Logger.send("Not authorized because does not have required attribute.")
|
88
116
|
return false
|
117
|
+
elsif !has_required_attribute_presence?
|
118
|
+
DeviseLdapAuthenticatable::Logger.send("Not authorized because does not have required attribute present.")
|
119
|
+
return false
|
89
120
|
else
|
90
121
|
return true
|
91
122
|
end
|
92
123
|
end
|
93
124
|
|
125
|
+
def expired_valid_credentials?
|
126
|
+
DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
|
127
|
+
|
128
|
+
!authenticated? && last_message_expired_credentials?
|
129
|
+
end
|
130
|
+
|
94
131
|
def change_password!
|
95
|
-
update_ldap(:
|
132
|
+
update_ldap(:userPassword => ::Devise.ldap_auth_password_builder.call(@new_password))
|
96
133
|
end
|
97
134
|
|
98
135
|
def in_required_groups?
|
99
|
-
return true unless @check_group_membership
|
136
|
+
return true unless @check_group_membership || @check_group_membership_without_admin
|
100
137
|
|
101
138
|
## FIXME set errors here, the ldap.yml isn't set properly.
|
102
139
|
return false if @required_groups.nil?
|
@@ -114,23 +151,29 @@ module Devise
|
|
114
151
|
def in_group?(group_name, group_attribute = LDAP::DEFAULT_GROUP_UNIQUE_MEMBER_LIST_KEY)
|
115
152
|
in_group = false
|
116
153
|
|
117
|
-
|
154
|
+
if @check_group_membership_without_admin
|
155
|
+
group_checking_ldap = @ldap
|
156
|
+
else
|
157
|
+
group_checking_ldap = Connection.admin
|
158
|
+
end
|
118
159
|
|
119
160
|
unless ::Devise.ldap_ad_group_check
|
120
|
-
|
161
|
+
group_checking_ldap.search(:base => group_name, :scope => Net::LDAP::SearchScope_BaseObject) do |entry|
|
121
162
|
if entry[group_attribute].include? dn
|
122
163
|
in_group = true
|
164
|
+
DeviseLdapAuthenticatable::Logger.send("User #{dn} IS included in group: #{group_name}")
|
123
165
|
end
|
124
166
|
end
|
125
167
|
else
|
126
168
|
# AD optimization - extension will recursively check sub-groups with one query
|
127
169
|
# "(memberof:1.2.840.113556.1.4.1941:=group_name)"
|
128
|
-
search_result =
|
170
|
+
search_result = group_checking_ldap.search(:base => dn,
|
129
171
|
:filter => Net::LDAP::Filter.ex("memberof:1.2.840.113556.1.4.1941", group_name),
|
130
172
|
:scope => Net::LDAP::SearchScope_BaseObject)
|
131
173
|
# Will return the user entry if belongs to group otherwise nothing
|
132
174
|
if search_result.length == 1 && search_result[0].dn.eql?(dn)
|
133
175
|
in_group = true
|
176
|
+
DeviseLdapAuthenticatable::Logger.send("User #{dn} IS included in group: #{group_name}")
|
134
177
|
end
|
135
178
|
end
|
136
179
|
|
@@ -145,11 +188,11 @@ module Devise
|
|
145
188
|
return true unless ::Devise.ldap_check_attributes
|
146
189
|
|
147
190
|
admin_ldap = Connection.admin
|
148
|
-
|
149
191
|
user = find_ldap_user(admin_ldap)
|
150
192
|
|
151
193
|
@required_attributes.each do |key,val|
|
152
|
-
|
194
|
+
matching_attributes = user[key] & Array(val)
|
195
|
+
unless (matching_attributes).any?
|
153
196
|
DeviseLdapAuthenticatable::Logger.send("User #{dn} did not match attribute #{key}:#{val}")
|
154
197
|
return false
|
155
198
|
end
|
@@ -158,11 +201,28 @@ module Devise
|
|
158
201
|
return true
|
159
202
|
end
|
160
203
|
|
204
|
+
def has_required_attribute_presence?
|
205
|
+
return true unless ::Devise.ldap_check_attributes_presence
|
206
|
+
|
207
|
+
user = search_for_login
|
208
|
+
|
209
|
+
@required_attributes_presence.each do |key,val|
|
210
|
+
if val && !user.attribute_names.include?(key.to_sym)
|
211
|
+
DeviseLdapAuthenticatable::Logger.send("User #{dn} doesn't include attribute #{key}")
|
212
|
+
return false
|
213
|
+
elsif !val && user.attribute_names.include?(key.to_sym)
|
214
|
+
DeviseLdapAuthenticatable::Logger.send("User #{dn} includes attribute #{key}")
|
215
|
+
return false
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
return true
|
220
|
+
end
|
221
|
+
|
161
222
|
def user_groups
|
162
223
|
admin_ldap = Connection.admin
|
163
|
-
|
164
224
|
DeviseLdapAuthenticatable::Logger.send("Getting groups for #{dn}")
|
165
|
-
filter = Net::LDAP::Filter.eq(
|
225
|
+
filter = Net::LDAP::Filter.eq(@group_membership_attribute, dn)
|
166
226
|
admin_ldap.search(:filter => filter, :base => @group_base).collect(&:dn)
|
167
227
|
end
|
168
228
|
|
@@ -174,13 +234,19 @@ module Devise
|
|
174
234
|
#
|
175
235
|
# @return [Object] the LDAP entry found; nil if not found
|
176
236
|
def search_for_login
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
237
|
+
@login_ldap_entry ||= begin
|
238
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP search for login: #{@attribute}=#{@login}")
|
239
|
+
filter = Net::LDAP::Filter.eq(@attribute.to_s, @login.to_s)
|
240
|
+
ldap_entry = nil
|
241
|
+
match_count = 0
|
242
|
+
@ldap.search(:filter => filter) {|entry| ldap_entry = entry; match_count+=1}
|
243
|
+
op_result= @ldap.get_operation_result
|
244
|
+
if op_result.code!=0 then
|
245
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP Error #{op_result.code}: #{op_result.message}")
|
246
|
+
end
|
247
|
+
DeviseLdapAuthenticatable::Logger.send("LDAP search yielded #{match_count} matches")
|
248
|
+
ldap_entry
|
249
|
+
end
|
184
250
|
end
|
185
251
|
|
186
252
|
private
|
@@ -223,4 +289,4 @@ module Devise
|
|
223
289
|
end
|
224
290
|
end
|
225
291
|
end
|
226
|
-
end
|
292
|
+
end
|