houston-devise_ldap_authenticatable 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/CHANGELOG.md +7 -0
  4. data/Gemfile +8 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +131 -0
  7. data/Rakefile +16 -0
  8. data/devise_ldap_authenticatable.gemspec +34 -0
  9. data/lib/devise_ldap_authenticatable.rb +50 -0
  10. data/lib/devise_ldap_authenticatable/exception.rb +6 -0
  11. data/lib/devise_ldap_authenticatable/ldap_adapter.rb +292 -0
  12. data/lib/devise_ldap_authenticatable/logger.rb +11 -0
  13. data/lib/devise_ldap_authenticatable/model.rb +95 -0
  14. data/lib/devise_ldap_authenticatable/routes.rb +8 -0
  15. data/lib/devise_ldap_authenticatable/schema.rb +14 -0
  16. data/lib/devise_ldap_authenticatable/strategy.rb +19 -0
  17. data/lib/devise_ldap_authenticatable/version.rb +3 -0
  18. data/lib/generators/devise_ldap_authenticatable/install_generator.rb +62 -0
  19. data/lib/generators/devise_ldap_authenticatable/templates/ldap.yml +51 -0
  20. data/spec/ldap/.gitignore +2 -0
  21. data/spec/ldap/base.ldif +73 -0
  22. data/spec/ldap/clear.ldif +26 -0
  23. data/spec/ldap/local.schema +6 -0
  24. data/spec/ldap/openldap-data/.gitignore +2 -0
  25. data/spec/ldap/openldap-data/run/.gitignore +2 -0
  26. data/spec/ldap/openldap-data/run/.gitkeep +0 -0
  27. data/spec/ldap/run-server +31 -0
  28. data/spec/ldap/server.pem +38 -0
  29. data/spec/ldap/slapd-test.conf.erb +107 -0
  30. data/spec/rails_app/Rakefile +7 -0
  31. data/spec/rails_app/app/controllers/application_controller.rb +7 -0
  32. data/spec/rails_app/app/controllers/posts_controller.rb +15 -0
  33. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  34. data/spec/rails_app/app/helpers/posts_helper.rb +2 -0
  35. data/spec/rails_app/app/models/post.rb +2 -0
  36. data/spec/rails_app/app/models/user.rb +10 -0
  37. data/spec/rails_app/app/views/layouts/application.html.erb +26 -0
  38. data/spec/rails_app/app/views/posts/index.html.erb +2 -0
  39. data/spec/rails_app/config.ru +4 -0
  40. data/spec/rails_app/config/application.rb +46 -0
  41. data/spec/rails_app/config/boot.rb +13 -0
  42. data/spec/rails_app/config/cucumber.yml +8 -0
  43. data/spec/rails_app/config/database.yml +25 -0
  44. data/spec/rails_app/config/environment.rb +5 -0
  45. data/spec/rails_app/config/environments/development.rb +21 -0
  46. data/spec/rails_app/config/environments/production.rb +46 -0
  47. data/spec/rails_app/config/environments/test.rb +34 -0
  48. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  49. data/spec/rails_app/config/initializers/devise.rb +242 -0
  50. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  51. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  52. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  53. data/spec/rails_app/config/initializers/session_store.rb +8 -0
  54. data/spec/rails_app/config/ldap.yml +22 -0
  55. data/spec/rails_app/config/ldap_with_boolean_ssl.yml +22 -0
  56. data/spec/rails_app/config/ldap_with_erb.yml +23 -0
  57. data/spec/rails_app/config/ldap_with_uid.yml +18 -0
  58. data/spec/rails_app/config/locales/devise.en.yml +58 -0
  59. data/spec/rails_app/config/locales/en.yml +5 -0
  60. data/spec/rails_app/config/routes.rb +64 -0
  61. data/spec/rails_app/config/ssl_ldap.yml +21 -0
  62. data/spec/rails_app/config/ssl_ldap_with_erb.yml +23 -0
  63. data/spec/rails_app/config/ssl_ldap_with_uid.yml +18 -0
  64. data/spec/rails_app/db/migrate/20100708120448_devise_create_users.rb +40 -0
  65. data/spec/rails_app/db/schema.rb +35 -0
  66. data/spec/rails_app/features/manage_logins.feature +35 -0
  67. data/spec/rails_app/features/step_definitions/login_steps.rb +21 -0
  68. data/spec/rails_app/features/step_definitions/web_steps.rb +219 -0
  69. data/spec/rails_app/features/support/env.rb +58 -0
  70. data/spec/rails_app/features/support/paths.rb +38 -0
  71. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  72. data/spec/rails_app/lib/tasks/cucumber.rake +53 -0
  73. data/spec/rails_app/public/404.html +26 -0
  74. data/spec/rails_app/public/422.html +26 -0
  75. data/spec/rails_app/public/500.html +26 -0
  76. data/spec/rails_app/public/images/rails.png +0 -0
  77. data/spec/rails_app/public/javascripts/application.js +2 -0
  78. data/spec/rails_app/public/javascripts/controls.js +965 -0
  79. data/spec/rails_app/public/javascripts/dragdrop.js +974 -0
  80. data/spec/rails_app/public/javascripts/effects.js +1123 -0
  81. data/spec/rails_app/public/javascripts/prototype.js +4874 -0
  82. data/spec/rails_app/public/javascripts/rails.js +118 -0
  83. data/spec/rails_app/public/stylesheets/.gitkeep +0 -0
  84. data/spec/rails_app/script/cucumber +10 -0
  85. data/spec/rails_app/script/rails +6 -0
  86. data/spec/spec_helper.rb +47 -0
  87. data/spec/support/factories.rb +16 -0
  88. data/spec/unit/user_spec.rb +298 -0
  89. metadata +411 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 89918ad25f184bbc7f2a970aefc838ea1bcb3112
4
+ data.tar.gz: a49591f1d6db64218ccfc8bc64de2ab50149dc79
5
+ SHA512:
6
+ metadata.gz: ec24c958bfbb0ffb5e0c59c7010b860907da202517929ca1b9c9664769e7044bc01f1ace1fb09a9bbf947e5834cf79a375c4388ef50207ff569621a52f00ea85
7
+ data.tar.gz: ee8a4d73a63d2597faeb00a255820569812fe7b4d9d1db8d8eaef2f5556def0103ac2f085f35a60341b6c0c77d781ec9375740de744fe49940b82813a49eb5ee
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ .bundle
2
+ Gemfile.lock
3
+ log
4
+ *.sqlite3
5
+ test/ldap/openldap-data/*
6
+ !test/ldap/openldap-data/run
7
+ test/ldap/openldap-data/run/slapd.*
8
+ test/rails_app/tmp
9
+ pkg/*
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ CHANGELOG
2
+ =========
3
+
4
+ v0.8
5
+ ----
6
+
7
+ [Issue #102](https://github.com/cschiewek/devise_ldap_authenticatable/pull/102): Extract method in_group? from in_required_groups? and expose it to the model
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'ruby-debug', '>= 0.10.3', :platform => :mri_18
7
+ gem 'debugger', :platform => :ruby_19
8
+ end
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Curtis Schiewek
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,131 @@
1
+ Devise LDAP Authenticatable
2
+ ===========================
3
+ Devise LDAP Authenticatable is a LDAP based authentication strategy for the [Devise](http://github.com/plataformatec/devise) authentication framework.
4
+
5
+ If you are building applications for use within your organization which require authentication and you want to use LDAP, this plugin is for you.
6
+
7
+ 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.
8
+
9
+ 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)
10
+
11
+ Prerequisites
12
+ -------------
13
+ * devise ~> 2.0.0 (which requires rails ~> 3.1)
14
+ * net-ldap ~> 0.2.2
15
+
16
+ Usage
17
+ -----
18
+ In the Gemfile for your application:
19
+
20
+ gem "devise_ldap_authenticatable"
21
+
22
+ To get the latest version, pull directly from github instead of the gem:
23
+
24
+ gem "devise_ldap_authenticatable", :git => "git://github.com/cschiewek/devise_ldap_authenticatable.git"
25
+
26
+
27
+ Setup
28
+ -----
29
+ Run the rails generators for devise (please check the [devise](http://github.com/plataformatec/devise) documents for further instructions)
30
+
31
+ rails generate devise:install
32
+ rails generate devise MODEL_NAME
33
+
34
+ Run the rails generator for `devise_ldap_authenticatable`
35
+
36
+ rails generate devise_ldap_authenticatable:install [options]
37
+
38
+ This will install the sample.yml, update the devise.rb initializer, and update your user model. There are some options you can pass to it:
39
+
40
+ Options:
41
+
42
+ [--user-model=USER_MODEL] # Model to update
43
+ # Default: user
44
+ [--update-model] # Update model to change from database_authenticatable to ldap_authenticatable
45
+ # Default: true
46
+ [--add-rescue] # Update Application Controller with rescue_from for DeviseLdapAuthenticatable::LdapException
47
+ # Default: true
48
+ [--advanced] # Add advanced config options to the devise initializer
49
+
50
+ Querying LDAP
51
+ -------------
52
+ Given that `ldap_create_user` is set to true and you are authenticating with username, you can query an LDAP server for other attributes.
53
+
54
+ in your user model:
55
+
56
+ before_save :get_ldap_email
57
+
58
+ def get_ldap_email
59
+ self.email = Devise::LdapAdapter.get_ldap_param(self.username,"mail")
60
+ end
61
+
62
+ Configuration
63
+ -------------
64
+ In initializer `config/initializers/devise.rb` :
65
+
66
+ * `ldap_logger` _(default: true)_
67
+ * If set to true, will log LDAP queries to the Rails logger.
68
+
69
+ * `ldap_create_user` _(default: false)_
70
+ * If set to true, all valid LDAP users will be allowed to login and an appropriate user record will be created.
71
+ If set to false, you will have to create the user record before they will be allowed to login.
72
+
73
+ * `ldap_config` _(default: #{Rails.root}/config/ldap.yml)_
74
+ * Where to find the LDAP config file. Commented out to use the default, change if needed.
75
+
76
+ * `ldap_update_password` _(default: true)_
77
+ * When doing password resets, if true will update the LDAP server. Requires admin password in the ldap.yml
78
+
79
+ * `ldap_check_group_membership` _(default: false)_
80
+ * 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.
81
+
82
+ * `ldap_check_attributes` _(default: false)_
83
+ * 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.
84
+
85
+ * `ldap_use_admin_to_bind` _(default: false)_
86
+ * When set to true, the admin user will be used to bind to the LDAP server during authentication.
87
+
88
+ Advanced Configuration
89
+ ----------------------
90
+ These parameters will be added to `config/initializers/devise.rb` when you pass the `--advanced` switch to the generator:
91
+
92
+ * `ldap_auth_username_builder` _(default: `Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }`)_
93
+ * 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.
94
+
95
+ Troubleshooting
96
+ --------------
97
+ **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.
98
+
99
+ **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`.
100
+
101
+ Development guide
102
+ ------------
103
+ 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.
104
+
105
+ This seems to come out of the box with Mac OS X 10.6.
106
+
107
+ On Ubuntu (tested on 12.04 and 12.10), you can run `sudo apt-get install slapd ldap-utils`. You will also likely have to add the `spec/ldap` directory of your local git clone to the slapd [apparmor](https://wiki.ubuntu.com/DebuggingApparmor) profile `/etc/apparmor.d/usr.sbin.slapd` if you get permissions errors. Something like this should do:
108
+
109
+ /path/to/devise_ldap_authenticatable/spec/ldap/** rw,$
110
+
111
+ To start hacking on `devise_ldap_authentication`, clone the github repository, start the test LDAP server, and run the rake test task:
112
+
113
+ git clone https://github.com/cschiewek/devise_ldap_authenticatable.git
114
+ cd devise_ldap_authenticatable
115
+ bundle install
116
+
117
+ # in a separate console or backgrounded
118
+ ./spec/ldap/run-server
119
+
120
+ bundle exec rake db:migrate # first time only
121
+ bundle exec rake spec
122
+
123
+ References
124
+ ----------
125
+ * [OpenLDAP](http://www.openldap.org/)
126
+ * [Devise](http://github.com/plataformatec/devise)
127
+ * [Warden](http://github.com/hassox/warden)
128
+
129
+ Released under the MIT license
130
+
131
+ Copyright (c) 2012 [Curtis Schiewek](https://github.com/cschiewek), [Daniel McNevin](https://github.com/dpmcnevin), [Steven Xu](https://github.com/cairo140)
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require File.expand_path('spec/rails_app/config/environment', File.dirname(__FILE__))
2
+ require 'rdoc/task'
3
+
4
+ desc 'Default: run test suite.'
5
+ task :default => :spec
6
+
7
+ desc 'Generate documentation for the devise_ldap_authenticatable plugin.'
8
+ Rake::RDocTask.new(:rdoc) do |rdoc|
9
+ rdoc.rdoc_dir = 'rdoc'
10
+ rdoc.title = 'DeviseLDAPAuthenticatable'
11
+ rdoc.options << '--line-numbers' << '--inline-source'
12
+ rdoc.rdoc_files.include('README.md')
13
+ rdoc.rdoc_files.include('lib/**/*.rb')
14
+ end
15
+
16
+ RailsApp::Application.load_tasks
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "devise_ldap_authenticatable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'houston-devise_ldap_authenticatable'
7
+ s.version = DeviseLdapAuthenticatable::VERSION.dup
8
+ s.platform = Gem::Platform::RUBY
9
+ s.summary = 'Devise extension to allow authentication via LDAP'
10
+ s.email = 'curtis.schiewek@gmail.com'
11
+ s.homepage = 'https://github.com/cschiewek/devise_ldap_authenticatable'
12
+ s.description = s.summary
13
+ s.authors = ['Curtis Schiewek', 'Daniel McNevin', 'Steven Xu']
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency('devise', '~> 3.0.0')
21
+ s.add_dependency('net-ldap', '~> 0.2')
22
+
23
+ s.add_development_dependency('rake', '>= 0.9')
24
+ s.add_development_dependency('rdoc', '>= 3')
25
+ s.add_development_dependency('rails', '~> 3.2')
26
+ s.add_development_dependency('sqlite3')
27
+ s.add_development_dependency('factory_girl_rails', '~> 1.0')
28
+ s.add_development_dependency('factory_girl', '~> 2.0')
29
+ s.add_development_dependency('rspec-rails')
30
+
31
+ %w{database_cleaner capybara launchy autotest-rails ZenTest autotest-growl}.each do |dep|
32
+ s.add_development_dependency(dep)
33
+ end
34
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ require 'devise'
3
+
4
+ require 'devise_ldap_authenticatable/exception'
5
+ require 'devise_ldap_authenticatable/logger'
6
+ require 'devise_ldap_authenticatable/schema'
7
+ require 'devise_ldap_authenticatable/ldap_adapter'
8
+ require 'devise_ldap_authenticatable/routes'
9
+
10
+ # Get ldap information from config/ldap.yml now
11
+ module Devise
12
+ # Allow logging
13
+ mattr_accessor :ldap_logger
14
+ @@ldap_logger = true
15
+
16
+ # Add valid users to database
17
+ mattr_accessor :ldap_create_user
18
+ @@ldap_create_user = false
19
+
20
+ mattr_accessor :ldap_config
21
+ # @@ldap_config = "#{Rails.root}/config/ldap.yml"
22
+
23
+ mattr_accessor :ldap_configuration
24
+
25
+ mattr_accessor :ldap_update_password
26
+ @@ldap_update_password = true
27
+
28
+ mattr_accessor :ldap_check_group_membership
29
+ @@ldap_check_group_membership = false
30
+
31
+ mattr_accessor :ldap_check_attributes
32
+ @@ldap_check_role_attribute = false
33
+
34
+ mattr_accessor :ldap_use_admin_to_bind
35
+ @@ldap_use_admin_to_bind = false
36
+
37
+ mattr_accessor :ldap_auth_username_builder
38
+ @@ldap_auth_username_builder = Proc.new() {|attribute, login, ldap| "#{attribute}=#{login},#{ldap.base}" }
39
+
40
+ mattr_accessor :ldap_ad_group_check
41
+ @@ldap_ad_group_check = false
42
+ end
43
+
44
+ # Add ldap_authenticatable strategy to defaults.
45
+ #
46
+ Devise.add_module(:ldap_authenticatable,
47
+ :route => :session, ## This will add the routes, rather than in the routes.rb
48
+ :strategy => true,
49
+ :controller => :sessions,
50
+ :model => 'devise_ldap_authenticatable/model')
@@ -0,0 +1,6 @@
1
+ module DeviseLdapAuthenticatable
2
+
3
+ class LdapException < Exception
4
+ end
5
+
6
+ end
@@ -0,0 +1,292 @@
1
+ require "net/ldap"
2
+
3
+ module Devise
4
+ module LdapAdapter
5
+ DEFAULT_GROUP_UNIQUE_MEMBER_LIST_KEY = 'uniqueMember'
6
+
7
+ def self.valid_credentials?(login, password_plaintext)
8
+ options = {:login => login,
9
+ :password => password_plaintext,
10
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
11
+ :admin => ::Devise.ldap_use_admin_to_bind}
12
+
13
+ resource = LdapConnect.new(options)
14
+ resource.authorized?
15
+ end
16
+
17
+ def self.update_password(login, new_password)
18
+ options = {:login => login,
19
+ :new_password => new_password,
20
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
21
+ :admin => ::Devise.ldap_use_admin_to_bind}
22
+
23
+ resource = LdapConnect.new(options)
24
+ resource.change_password! if new_password.present?
25
+ end
26
+
27
+ def self.update_own_password(login, new_password, current_password)
28
+ set_ldap_param(login, :userpassword, new_password, current_password)
29
+ end
30
+
31
+ def self.ldap_connect(login)
32
+ options = {:login => login,
33
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
34
+ :admin => ::Devise.ldap_use_admin_to_bind}
35
+
36
+ resource = LdapConnect.new(options)
37
+ end
38
+
39
+ def self.valid_login?(login)
40
+ self.ldap_connect(login).valid_login?
41
+ end
42
+
43
+ def self.get_groups(login)
44
+ self.ldap_connect(login).user_groups
45
+ end
46
+
47
+ def self.in_ldap_group?(login, group_name, group_attribute = nil)
48
+ self.ldap_connect(login).in_group?(group_name, group_attribute)
49
+ end
50
+
51
+ def self.get_dn(login)
52
+ self.ldap_connect(login).dn
53
+ end
54
+
55
+ def self.set_ldap_param(login, param, new_value, password = nil)
56
+ options = { :login => login,
57
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
58
+ :password => password }
59
+
60
+ resource = LdapConnect.new(options)
61
+ resource.set_param(param, new_value)
62
+ end
63
+
64
+ def self.delete_ldap_param(login, param, password = nil)
65
+ options = { :login => login,
66
+ :ldap_auth_username_builder => ::Devise.ldap_auth_username_builder,
67
+ :password => password }
68
+
69
+ resource = LdapConnect.new(options)
70
+ resource.delete_param(param)
71
+ end
72
+
73
+ def self.get_ldap_param(login,param)
74
+ resource = self.ldap_connect(login)
75
+ resource.ldap_param_value(param)
76
+ end
77
+
78
+ def self.get_ldap_entry(login)
79
+ self.ldap_connect(login).search_for_login
80
+ end
81
+
82
+ class LdapConnect
83
+
84
+ attr_reader :ldap, :login
85
+
86
+ def initialize(params = {})
87
+ ldap_config = ::Devise.ldap_configuration
88
+ ldap_config ||= YAML.load(ERB.new(File.read(::Devise.ldap_config || "#{Rails.root}/config/ldap.yml")).result)[Rails.env]
89
+ ldap_options = params
90
+ ldap_config["ssl"] = :simple_tls if ldap_config["ssl"] === true
91
+ ldap_options[:encryption] = ldap_config["ssl"].to_sym if ldap_config["ssl"]
92
+
93
+ @ldap = Net::LDAP.new(ldap_options)
94
+ @ldap.host = ldap_config["host"]
95
+ @ldap.port = ldap_config["port"]
96
+ @ldap.base = ldap_config["base"]
97
+ @attribute = ldap_config["attribute"]
98
+ @ldap_auth_username_builder = params[:ldap_auth_username_builder]
99
+
100
+ @group_base = ldap_config["group_base"]
101
+ @check_group_membership = ldap_config.has_key?("check_group_membership") ? ldap_config["check_group_membership"] : ::Devise.ldap_check_group_membership
102
+ @required_groups = ldap_config["required_groups"]
103
+ @required_attributes = ldap_config["require_attribute"]
104
+
105
+ @ldap.auth ldap_config["admin_user"], ldap_config["admin_password"] if params[:admin]
106
+
107
+ @login = params[:login]
108
+ @password = params[:password]
109
+ @new_password = params[:new_password]
110
+ end
111
+
112
+ def delete_param(param)
113
+ update_ldap [[:delete, param.to_sym, nil]]
114
+ end
115
+
116
+ def set_param(param, new_value)
117
+ update_ldap( { param.to_sym => new_value } )
118
+ end
119
+
120
+ def dn
121
+ DeviseLdapAuthenticatable::Logger.send("LDAP dn lookup: #{@attribute}=#{@login}")
122
+ ldap_entry = search_for_login
123
+ if ldap_entry.nil?
124
+ @ldap_auth_username_builder.call(@attribute,@login,@ldap)
125
+ else
126
+ ldap_entry.dn
127
+ end
128
+ end
129
+
130
+ def ldap_param_value(param)
131
+ filter = Net::LDAP::Filter.eq(@attribute.to_s, @login.to_s)
132
+ ldap_entry = nil
133
+ @ldap.search(:filter => filter) {|entry| ldap_entry = entry}
134
+
135
+ if ldap_entry
136
+ if ldap_entry[param]
137
+ DeviseLdapAuthenticatable::Logger.send("Requested param #{param} has value #{ldap_entry.send(param)}")
138
+ value = ldap_entry.send(param)
139
+ value = value.first if value.is_a?(Array) and value.count == 1
140
+ value
141
+ else
142
+ DeviseLdapAuthenticatable::Logger.send("Requested param #{param} does not exist")
143
+ value = nil
144
+ end
145
+ else
146
+ DeviseLdapAuthenticatable::Logger.send("Requested ldap entry does not exist")
147
+ value = nil
148
+ end
149
+ end
150
+
151
+ def authenticate!
152
+ @ldap.auth(dn, @password)
153
+ @ldap.bind
154
+ end
155
+
156
+ def authenticated?
157
+ authenticate!
158
+ end
159
+
160
+ def authorized?
161
+ DeviseLdapAuthenticatable::Logger.send("Authorizing user #{dn}")
162
+ authenticated? && in_required_groups? && has_required_attribute?
163
+ end
164
+
165
+ def change_password!
166
+ update_ldap(:userpassword => Net::LDAP::Password.generate(:sha, @new_password))
167
+ end
168
+
169
+ def in_required_groups?
170
+ return true unless @check_group_membership
171
+
172
+ ## FIXME set errors here, the ldap.yml isn't set properly.
173
+ return false if @required_groups.nil?
174
+
175
+ for group in @required_groups
176
+ unless in_group?(*group)
177
+ return false
178
+ end
179
+ end
180
+ return true
181
+ end
182
+
183
+ def in_group?(group_name, group_attribute = DEFAULT_GROUP_UNIQUE_MEMBER_LIST_KEY)
184
+ admin_ldap = LdapConnect.admin
185
+
186
+ unless ::Devise.ldap_ad_group_check
187
+ admin_ldap.search(:base => group_name, :scope => Net::LDAP::SearchScope_BaseObject) do |entry|
188
+ unless entry[group_attribute].include? dn
189
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} is not in group: #{group_name }")
190
+ return false
191
+ end
192
+ end
193
+ else
194
+ # AD optimization - extension will recursively check sub-groups with one query
195
+ # "(memberof:1.2.840.113556.1.4.1941:=group_name)"
196
+ search_result = admin_ldap.search(:base => dn,
197
+ :filter => Net::LDAP::Filter.ex("memberof:1.2.840.113556.1.4.1941", group_name),
198
+ :scope => Net::LDAP::SearchScope_BaseObject)
199
+ # Will return the user entry if belongs to group otherwise nothing
200
+ unless search_result.length == 1 && search_result[0].dn.eql?(dn)
201
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} is not in group: #{group_name }")
202
+ return false
203
+ end
204
+ end
205
+
206
+ return true
207
+ end
208
+
209
+ def has_required_attribute?
210
+ return true unless ::Devise.ldap_check_attributes
211
+
212
+ admin_ldap = LdapConnect.admin
213
+
214
+ user = find_ldap_user(admin_ldap)
215
+
216
+ @required_attributes.each do |key,val|
217
+ unless user[key].include? val
218
+ DeviseLdapAuthenticatable::Logger.send("User #{dn} did not match attribute #{key}:#{val}")
219
+ return false
220
+ end
221
+ end
222
+
223
+ return true
224
+ end
225
+
226
+ def user_groups
227
+ admin_ldap = LdapConnect.admin
228
+
229
+ DeviseLdapAuthenticatable::Logger.send("Getting groups for #{dn}")
230
+ filter = Net::LDAP::Filter.eq("uniqueMember", dn)
231
+ admin_ldap.search(:filter => filter, :base => @group_base).collect(&:dn)
232
+ end
233
+
234
+ def valid_login?
235
+ !search_for_login.nil?
236
+ end
237
+
238
+ # Searches the LDAP for the login
239
+ #
240
+ # @return [Object] the LDAP entry found; nil if not found
241
+ def search_for_login
242
+ DeviseLdapAuthenticatable::Logger.send("LDAP search for login: #{@attribute}=#{@login}")
243
+ filter = Net::LDAP::Filter.eq(@attribute.to_s, @login.to_s)
244
+ ldap_entry = nil
245
+ @ldap.search(:filter => filter) {|entry| ldap_entry = entry}
246
+ ldap_entry
247
+ end
248
+
249
+ private
250
+
251
+ def self.admin
252
+ ldap = LdapConnect.new(:admin => true).ldap
253
+
254
+ unless ldap.bind
255
+ DeviseLdapAuthenticatable::Logger.send("Cannot bind to admin LDAP user")
256
+ raise DeviseLdapAuthenticatable::LdapException, "Cannot connect to admin LDAP user"
257
+ end
258
+
259
+ return ldap
260
+ end
261
+
262
+ def find_ldap_user(ldap)
263
+ DeviseLdapAuthenticatable::Logger.send("Finding user: #{dn}")
264
+ ldap.search(:base => dn, :scope => Net::LDAP::SearchScope_BaseObject).try(:first)
265
+ end
266
+
267
+ def update_ldap(ops)
268
+ operations = []
269
+ if ops.is_a? Hash
270
+ ops.each do |key,value|
271
+ operations << [:replace,key,value]
272
+ end
273
+ elsif ops.is_a? Array
274
+ operations = ops
275
+ end
276
+
277
+ if ::Devise.ldap_use_admin_to_bind
278
+ privileged_ldap = LdapConnect.admin
279
+ else
280
+ authenticate!
281
+ privileged_ldap = self.ldap
282
+ end
283
+
284
+ DeviseLdapAuthenticatable::Logger.send("Modifying user #{dn}")
285
+ privileged_ldap.modify(:dn => dn, :operations => operations)
286
+ end
287
+
288
+ end
289
+
290
+ end
291
+
292
+ end