devise_saml_authenticatable 1.3.2 → 1.6.1

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 (37) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -2
  3. data/.travis.yml +29 -22
  4. data/Gemfile +2 -2
  5. data/README.md +105 -32
  6. data/app/controllers/devise/saml_sessions_controller.rb +35 -7
  7. data/devise_saml_authenticatable.gemspec +2 -1
  8. data/lib/devise_saml_authenticatable.rb +27 -2
  9. data/lib/devise_saml_authenticatable/default_attribute_map_resolver.rb +26 -0
  10. data/lib/devise_saml_authenticatable/default_idp_entity_id_reader.rb +2 -0
  11. data/lib/devise_saml_authenticatable/exception.rb +1 -1
  12. data/lib/devise_saml_authenticatable/model.rb +16 -18
  13. data/lib/devise_saml_authenticatable/routes.rb +17 -6
  14. data/lib/devise_saml_authenticatable/saml_mapped_attributes.rb +15 -2
  15. data/lib/devise_saml_authenticatable/strategy.rb +1 -0
  16. data/lib/devise_saml_authenticatable/version.rb +1 -1
  17. data/spec/controllers/devise/saml_sessions_controller_spec.rb +118 -11
  18. data/spec/devise_saml_authenticatable/default_attribute_map_resolver_spec.rb +58 -0
  19. data/spec/devise_saml_authenticatable/model_spec.rb +68 -7
  20. data/spec/devise_saml_authenticatable/saml_mapped_attributes_spec.rb +50 -0
  21. data/spec/features/saml_authentication_spec.rb +45 -21
  22. data/spec/rails_helper.rb +6 -2
  23. data/spec/routes/routes_spec.rb +102 -0
  24. data/spec/spec_helper.rb +7 -0
  25. data/spec/support/Gemfile.rails4 +23 -6
  26. data/spec/support/Gemfile.rails5 +13 -2
  27. data/spec/support/Gemfile.rails5.1 +25 -0
  28. data/spec/support/Gemfile.rails5.2 +25 -0
  29. data/spec/support/attribute-map.yml +12 -0
  30. data/spec/support/attribute_map_resolver.rb.erb +14 -0
  31. data/spec/support/idp_settings_adapter.rb.erb +5 -5
  32. data/spec/support/idp_template.rb +6 -2
  33. data/spec/support/rails_app.rb +75 -17
  34. data/spec/support/saml_idp_controller.rb.erb +13 -6
  35. data/spec/support/sp_template.rb +45 -21
  36. metadata +25 -13
  37. data/spec/support/Gemfile.ruby-saml-1.3 +0 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 269c0505d92b49c3b9a79d1b8aece87533018b10
4
- data.tar.gz: 259f7e012808aabe3ab06e854a01deab8959843a
2
+ SHA256:
3
+ metadata.gz: d3ca38cfe51cdf71fc8a264de868fc285bfa413307aa4798e097fbf88e85020d
4
+ data.tar.gz: 2371ef1371e29547b4eb9681066fa43f0b6d39236b7df8676236bf13678e2d01
5
5
  SHA512:
6
- metadata.gz: 83a89cbe087accbcf239e047027188a35793c9cdcb3198fd207edeb95652bb6e8957ef8e0aeaa9b919f01cbb91677bf4c5ade49fae0a85b86cf95edc4b09592b
7
- data.tar.gz: 230f5490186a0853cd63f401b390afa29129b8f103de04cbb64a734274edd88de9467030784122cccdc743fbd5eb7babf75ad3635be5b51d2a5af467d4e17b1f
6
+ metadata.gz: 872bfb214a00504735d9183d169e4119ebb9c6ae3129de729be642f39c4675b57040bb1c9d46899e73d534aa82d7ac9291c425109c10eaeb290831480e7976ab
7
+ data.tar.gz: 3269ef293937aef443afa9a325acc0addf027c3ad7421865a9ebe1554d7215461767ffe9e34cd4cc2bf8edbae831e7e342dd3c47245d57209d8ddd820a128212
data/.gitignore CHANGED
@@ -13,6 +13,4 @@ lib/bundler/man
13
13
  pkg
14
14
  rdoc
15
15
  spec/reports
16
- spec/support/idp/
17
- spec/support/sp/
18
16
  tmp
@@ -1,45 +1,52 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "1.9.3"
4
3
  - "2.0.0"
5
4
  - "2.1.10"
6
- - "2.2.7"
7
- - "2.3.4"
8
- - "2.4.1"
5
+ - "2.2.10"
6
+ - "2.3.8"
7
+ - "2.4.10"
8
+ - "2.5.8"
9
+ - "2.6.6"
10
+ - "2.7.1"
9
11
  gemfile:
10
12
  - Gemfile
13
+ - spec/support/Gemfile.rails5.2
14
+ - spec/support/Gemfile.rails5.1
11
15
  - spec/support/Gemfile.rails5
12
16
  - spec/support/Gemfile.rails4
13
- - spec/support/Gemfile.ruby-saml-1.3
14
17
  matrix:
15
18
  allow_failures:
16
- - rvm: "1.9.3"
17
- gemfile: Gemfile
18
- - rvm: "1.9.3"
19
- gemfile: spec/support/Gemfile.rails5
20
- - rvm: "1.9.3"
21
- gemfile: spec/support/Gemfile.ruby-saml-1.3
22
19
  - rvm: "2.0.0"
23
20
  gemfile: Gemfile
24
21
  - rvm: "2.0.0"
25
22
  gemfile: spec/support/Gemfile.rails5
26
23
  - rvm: "2.0.0"
27
- gemfile: spec/support/Gemfile.ruby-saml-1.3
24
+ gemfile: spec/support/Gemfile.rails5.1
25
+ - rvm: "2.0.0"
26
+ gemfile: spec/support/Gemfile.rails5.2
28
27
  - rvm: "2.1.10"
29
28
  gemfile: Gemfile
30
29
  - rvm: "2.1.10"
31
30
  gemfile: spec/support/Gemfile.rails5
32
31
  - rvm: "2.1.10"
33
- gemfile: spec/support/Gemfile.ruby-saml-1.3
32
+ gemfile: spec/support/Gemfile.rails5.1
33
+ - rvm: "2.1.10"
34
+ gemfile: spec/support/Gemfile.rails5.2
35
+ - rvm: "2.2.10"
36
+ gemfile: Gemfile
37
+ - rvm: "2.2.10"
38
+ gemfile: spec/support/Gemfile.rails5.2
39
+ - rvm: "2.3.8"
40
+ gemfile: Gemfile
41
+ - rvm: "2.4.10"
42
+ gemfile: Gemfile
43
+ - rvm: "2.6.6"
44
+ gemfile: spec/support/Gemfile.rails4
45
+ - rvm: "2.7.1"
46
+ gemfile: spec/support/Gemfile.rails4
47
+
48
+ before_install:
49
+ - command -v bundle || gem install bundler -v '~> 1.17.3'
34
50
 
35
51
  script:
36
52
  - bundle exec rake
37
-
38
- notifications:
39
- hipchat:
40
- rooms:
41
- secure: cuDak5a6fBeg+sp61COqxQfzdcFEsjwCqtwvCISso0RNh5SR8v+uVYKcA8rlK+GE1l9uR7tLRHeHF3ZmzvFSOat07NvpScvjZXi+OSpWlc6rwQ6Pl6bBP6gu6sREiKVe0eT/uGrvJloyWKZaXIhiiBzQ+ZERx/ssGA9WMmNkhlwy1OgGnPNurNNHZLBjEZn1V6kdyxiXx6QPASNpjNEgN1G8dUh3qzcWUGVQGNZSJk65A6ie1MveNyecTjDhw+ADBU8nS28Ja4y6ohRm4FzofSgespYrvfygIZ5rYF0HPMj5FW1ZDWtM5355ojCk8RLT+ZkuhssCn1OJk7ogaOVjnYcOFRxEfpu3eIbjtMmUz3j4umatFqbgas+6SXMVIPkr5HUoTrP8HNFssIpcEBOnPwAF8QCpx+daHc0r2cc8lGuXhtJfpW0P2F0dmwJNiQ7//nz2y2xs84x4Gb7MV9tEDYp0FqEClMuFBkPNizBljarm04PkiLSrqvR52aMDfQz7YAX2oXAvFjPzI1GC0K8x7xX8TuHT9yuHy7fI+rUSNivZYLKO+IEZqPPDdJpXISUbVwanZoNvmQYk5PZV21MfDSGwQrz8eO/uFiAblj18yIlNbAfb2hdZDVYsm4EvWxELJtfaTxgrj6M3Y3m/KbCbCoDp+2jE307M2rxL0Gum2gk=
42
- template:
43
- - '%{repository}<a href="%{build_url}">#%{build_number}</a> (%{branch} - <a href="%{compare_url}">%{commit}</a> : %{author}): %{message}'
44
- format: html
45
- on_pull_requests: true
data/Gemfile CHANGED
@@ -6,9 +6,9 @@ gemspec
6
6
  group :test do
7
7
  gem 'rake'
8
8
  gem 'rspec', '~> 3.0'
9
- gem 'rails', '~> 5.1'
9
+ gem 'rails', '~> 6.0'
10
10
  gem 'rspec-rails'
11
- gem 'sqlite3'
11
+ gem 'sqlite3', '~> 1.4.0'
12
12
  gem 'capybara'
13
13
  gem 'poltergeist'
14
14
  end
data/README.md CHANGED
@@ -6,19 +6,20 @@ It uses [ruby-saml][] to handle all SAML-related stuff.
6
6
 
7
7
  ## Installation
8
8
 
9
- Add this line to your application's Gemfile:
9
+ Add this gem to your application's Gemfile:
10
10
 
11
- gem 'devise_saml_authenticatable'
11
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
12
+ gem "devise_saml_authenticatable", github: "apokalipto/devise_saml_authenticatable"
12
13
 
13
14
  And then execute:
14
15
 
15
16
  $ bundle
16
17
 
17
- Or install it yourself as:
18
+ ## Usage
18
19
 
19
- $ gem install devise_saml_authenticatable
20
+ Follow the [normal devise installation process](https://github.com/plataformatec/devise/tree/master#getting-started). The controller filters and helpers are unchanged from normal devise usage.
20
21
 
21
- ## Usage
22
+ ### Configuring Models
22
23
 
23
24
  In `app/models/<YOUR_MODEL>.rb` set the `:saml_authenticatable` strategy.
24
25
 
@@ -32,6 +33,37 @@ In the example the model is `user.rb`:
32
33
  end
33
34
  ```
34
35
 
36
+ ### Configuring routes
37
+
38
+ In `config/routes.rb` add `devise_for` to set up helper methods and routes:
39
+
40
+ ```ruby
41
+ devise_for :users
42
+ ```
43
+
44
+ The named routes can be customized in the initializer config file.
45
+
46
+ ### Configuring the IdP
47
+
48
+ An extra step in SAML SSO setup is adding your application to your identity provider. The required setup is specific to each IdP, but we have some examples in [our wiki](https://github.com/apokalipto/devise_saml_authenticatable/wiki). You'll need to tell your IdP how to send requests and responses to your application.
49
+
50
+ - Creating a new session: `/users/saml/auth`
51
+ - IdPs may call this the "consumer," "recipient," "destination," or even "single sign-on." This is where they send a SAML response for an authenticated user.
52
+ - Metadata: `/users/saml/metadata`
53
+ - IdPs may call this the "audience."
54
+ - Single Logout: `/users/saml/idp_sign_out`
55
+ - if desired, you can ask the IdP to send a Logout request to this endpoint to sign the user out of your application when they sign out of the IdP itself.
56
+
57
+ Your IdP should give you some information you need to configure in [ruby-saml](https://github.com/onelogin/ruby-saml), as in the next section:
58
+
59
+ - Issuer (`idp_entity_id`)
60
+ - SSO endpoint (`idp_sso_target_url`)
61
+ - SLO endpoint (`idp_slo_target_url`)
62
+ - Certificate fingerprint (`idp_cert_fingerprint`) and algorithm (`idp_cert_fingerprint_algorithm`)
63
+ - Or the certificate itself (`idp_cert`)
64
+
65
+ ### Configuring handling of IdP requests and responses
66
+
35
67
  In `config/initializers/devise.rb`:
36
68
 
37
69
  ```ruby
@@ -69,8 +101,19 @@ In `config/initializers/devise.rb`:
69
101
  # and implements a #handle method. This method can then redirect the user, return error messages, etc.
70
102
  # config.saml_failed_callback = nil
71
103
 
72
- # Configure with your SAML settings (see [ruby-saml][] for more information).
104
+ # You can customize the named routes generated in case of named route collisions with
105
+ # other Devise modules or libraries. Set the saml_route_helper_prefix to a string that will
106
+ # be appended to the named route.
107
+ # If saml_route_helper_prefix = 'saml' then the new_user_session route becomes new_saml_user_session
108
+ # config.saml_route_helper_prefix = 'saml'
109
+
110
+ # You can add allowance for clock drift between the sp and idp.
111
+ # This is a time in seconds.
112
+ # config.allowed_clock_drift_in_seconds = 0
113
+
114
+ # Configure with your SAML settings (see ruby-saml's README for more information: https://github.com/onelogin/ruby-saml).
73
115
  config.saml_configure do |settings|
116
+ # assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
74
117
  settings.assertion_consumer_service_url = "http://localhost:3000/users/saml/auth"
75
118
  settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
76
119
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
@@ -78,29 +121,32 @@ In `config/initializers/devise.rb`:
78
121
  settings.authn_context = ""
79
122
  settings.idp_slo_target_url = "http://localhost/simplesaml/www/saml2/idp/SingleLogoutService.php"
80
123
  settings.idp_sso_target_url = "http://localhost/simplesaml/www/saml2/idp/SSOService.php"
81
- settings.idp_cert = <<-CERT.chomp
82
- -----BEGIN CERTIFICATE-----
83
- 1111111111111111111111111111111111111111111111111111111111111111
84
- 1111111111111111111111111111111111111111111111111111111111111111
85
- 1111111111111111111111111111111111111111111111111111111111111111
86
- 1111111111111111111111111111111111111111111111111111111111111111
87
- 1111111111111111111111111111111111111111111111111111111111111111
88
- 1111111111111_______IDP_CERTIFICATE________111111111111111111111
89
- 1111111111111111111111111111111111111111111111111111111111111111
90
- 1111111111111111111111111111111111111111111111111111111111111111
91
- 1111111111111111111111111111111111111111111111111111111111111111
92
- 1111111111111111111111111111111111111111111111111111111111111111
93
- 1111111111111111111111111111111111111111111111111111111111111111
94
- 1111111111111111111111111111111111111111111111111111111111111111
95
- 1111111111111111111111111111111111111111111111111111111111111111
96
- 111111111111111111
97
- -----END CERTIFICATE-----
98
- CERT
124
+ settings.idp_cert_fingerprint = "00:A1:2B:3C:44:55:6F:A7:88:CC:DD:EE:22:33:44:55:D6:77:8F:99"
125
+ settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
99
126
  end
100
127
  end
101
128
  ```
102
129
 
103
- In the config directory, create a YAML file (`attribute-map.yml`) that maps SAML attributes with your model's fields:
130
+ #### Attributes
131
+
132
+ There are two ways to map SAML attributes to User attributes:
133
+
134
+ - [initializer](#attribute-map-initializer)
135
+ - [config file](#attribute-map-config-file)
136
+
137
+ The attribute mappings are very dependent on the way the IdP encodes the attributes.
138
+ In these examples the attributes are given in URN style.
139
+ Other IdPs might provide them as OID's, or by other means.
140
+
141
+ You are now ready to test it against an IdP.
142
+
143
+ When the user visits `/users/saml/sign_in` they will be redirected to the login page of the IdP.
144
+
145
+ Upon successful login the user is redirected to the Devise `user_root_path`.
146
+
147
+ ##### Attribute map config file
148
+
149
+ Create a YAML file (`config/attribute-map.yml`) that maps SAML attributes with your model's fields:
104
150
 
105
151
  ```yaml
106
152
  # attribute-map.yml
@@ -111,15 +157,39 @@ In the config directory, create a YAML file (`attribute-map.yml`) that maps SAML
111
157
  "urn:mace:dir:attribute-def:givenName": "name"
112
158
  ```
113
159
 
114
- The attribute mappings are very dependent on the way the IdP encodes the attributes.
115
- In this example the attributes are given in URN style.
116
- Other IdPs might provide them as OID's, or by other means.
160
+ ##### Attribute map initializer
117
161
 
118
- You are now ready to test it against an IdP.
162
+ In `config/initializers/devise.rb` (see above), add an attribute map resolver.
163
+ The resolver gets the [SAML response from the IdP](https://github.com/onelogin/ruby-saml/blob/master/lib/onelogin/ruby-saml/response.rb) so it can decide which attribute map to load.
164
+ If you only have one IdP, you can use the config file above, or just return a single hash.
119
165
 
120
- When the user visits `/users/saml/sign_in` they will be redirected to the login page of the IdP.
166
+ ```ruby
167
+ # config/initializers/devise.rb
168
+ Devise.setup do |config|
169
+ ...
170
+ # ==> Configuration for :saml_authenticatable
121
171
 
122
- Upon successful login the user is redirected to the Devise `user_root_path`.
172
+ config.saml_attribute_map_resolver = MyAttributeMapResolver
173
+ end
174
+ ```
175
+
176
+ ```ruby
177
+ # app/lib/my_attribute_map_resolver
178
+ class MyAttributeMapResolver < DeviseSamlAuthenticatable::DefaultAttributeMapResolver
179
+ def attribute_map
180
+ issuer = saml_response.issuers.first
181
+ case issuer
182
+ when "idp_entity_id"
183
+ {
184
+ "urn:mace:dir:attribute-def:uid" => "user_name",
185
+ "urn:mace:dir:attribute-def:email" => "email",
186
+ "urn:mace:dir:attribute-def:name" => "last_name",
187
+ "urn:mace:dir:attribute-def:givenName" => "name",
188
+ }
189
+ end
190
+ end
191
+ end
192
+ ```
123
193
 
124
194
  ## Supporting Multiple IdPs
125
195
 
@@ -159,6 +229,7 @@ class IdPSettingsAdapter
159
229
  end
160
230
  end
161
231
  ```
232
+ Settings specified in the adapter will override settings in `config/initializers/devise.rb`. This is useful for establishing common settings or defaults across all IdPs.
162
233
 
163
234
  Detecting the entity ID passed to the `settings` method is done by `config.idp_entity_id_reader`.
164
235
 
@@ -192,10 +263,12 @@ Logout requests from the IDP are supported by the `idp_sign_out` endpoint. Dire
192
263
 
193
264
  `saml_session_index_key` must be configured to support this feature.
194
265
 
195
- ## Signing and Encrypting Authentication Requests
266
+ ## Signing and Encrypting Authentication Requests and Assertions
196
267
 
197
268
  ruby-saml 1.0.0 supports signature and decrypt. The only requirement is to set the public certificate and the private key. For more information, see [the ruby-saml documentation](https://github.com/onelogin/ruby-saml#signing).
198
269
 
270
+ If you have multiple IdPs, the certificate and private key must be in the shared settings in `config/initializers/devise.rb`.
271
+
199
272
  ## Thanks
200
273
 
201
274
  The continued maintenance of this gem could not have been possible without the hard work of [Adam Stegman](https://github.com/adamstegman) and [Mitch Lindsay](https://github.com/mitch-lindsay). Thank you guys for keeping this project alive.
@@ -5,8 +5,10 @@ class Devise::SamlSessionsController < Devise::SessionsController
5
5
  unloadable if Rails::VERSION::MAJOR < 4
6
6
  if Rails::VERSION::MAJOR < 5
7
7
  skip_before_filter :verify_authenticity_token
8
+ prepend_before_filter :store_info_for_sp_initiated_logout, only: :destroy
8
9
  else
9
10
  skip_before_action :verify_authenticity_token, raise: false
11
+ prepend_before_action :store_info_for_sp_initiated_logout, only: :destroy
10
12
  end
11
13
 
12
14
  def new
@@ -18,8 +20,9 @@ class Devise::SamlSessionsController < Devise::SessionsController
18
20
  end
19
21
 
20
22
  def metadata
23
+ idp_entity_id = params[:idp_entity_id]
21
24
  meta = OneLogin::RubySaml::Metadata.new
22
- render :xml => meta.generate(saml_config)
25
+ render :xml => meta.generate(saml_config(idp_entity_id))
23
26
  end
24
27
 
25
28
  def idp_sign_out
@@ -30,16 +33,16 @@ class Devise::SamlSessionsController < Devise::SessionsController
30
33
 
31
34
  redirect_to generate_idp_logout_response(saml_config, logout_request.id)
32
35
  elsif params[:SAMLResponse]
33
- #Currently Devise handles the session invalidation when the request is made.
34
- #To support a true SP initiated logout response, the request ID would have to be tracked and session invalidated
35
- #based on that.
36
+ # Currently Devise handles the session invalidation when the request is made.
37
+ # To support a true SP initiated logout response, the request ID would have to be tracked and session invalidated
38
+ # based on that.
36
39
  if Devise.saml_sign_out_success_url
37
40
  redirect_to Devise.saml_sign_out_success_url
38
41
  else
39
42
  redirect_to action: :new
40
43
  end
41
44
  else
42
- head :invalid_request
45
+ head 500
43
46
  end
44
47
  end
45
48
 
@@ -51,13 +54,38 @@ class Devise::SamlSessionsController < Devise::SessionsController
51
54
  end
52
55
  end
53
56
 
57
+ # For non transient name ID, save info to identify user for logout purpose
58
+ # before that user's session got destroyed. These info are used in the
59
+ # `after_sign_out_path_for` method below.
60
+ def store_info_for_sp_initiated_logout
61
+ return if Devise.saml_config.name_identifier_format == "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
62
+ @name_identifier_value_for_sp_initiated_logout = Devise.saml_name_identifier_retriever.call(current_user)
63
+ @sessionindex_for_sp_initiated_logout = current_user.public_send(Devise.saml_session_index_key) if Devise.saml_session_index_key
64
+ end
65
+
54
66
  # Override devise to send user to IdP logout for SLO
55
67
  def after_sign_out_path_for(_)
68
+ idp_entity_id = get_idp_entity_id(params)
56
69
  request = OneLogin::RubySaml::Logoutrequest.new
57
- request.create(saml_config)
70
+ saml_settings = saml_config(idp_entity_id).dup
71
+
72
+ # Add attributes to saml_settings which will later be used to create the SP
73
+ # initiated logout request
74
+ unless Devise.saml_config.name_identifier_format == 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
75
+ saml_settings.name_identifier_value = @name_identifier_value_for_sp_initiated_logout
76
+ saml_settings.sessionindex = @sessionindex_for_sp_initiated_logout
77
+ end
78
+
79
+ request.create(saml_settings)
58
80
  end
59
81
 
60
82
  def generate_idp_logout_response(saml_config, logout_request_id)
61
- OneLogin::RubySaml::SloLogoutresponse.new.create(saml_config, logout_request_id, nil)
83
+
84
+ params = {}
85
+ if relay_state
86
+ params[:RelayState] = relay_state
87
+ end
88
+
89
+ OneLogin::RubySaml::SloLogoutresponse.new.create(saml_config, logout_request_id, nil, params)
62
90
  end
63
91
  end
@@ -7,6 +7,7 @@ Gem::Specification.new do |gem|
7
7
  gem.description = %q{SAML Authentication for devise}
8
8
  gem.summary = %q{SAML Authentication for devise }
9
9
  gem.homepage = ""
10
+ gem.license = "MIT"
10
11
 
11
12
  gem.files = `git ls-files`.split($\)
12
13
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -17,5 +18,5 @@ Gem::Specification.new do |gem|
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
19
 
19
20
  gem.add_dependency("devise","> 2.0.0")
20
- gem.add_dependency("ruby-saml","~> 1.3")
21
+ gem.add_dependency("ruby-saml","~> 1.7")
21
22
  end
@@ -5,6 +5,7 @@ require "devise_saml_authenticatable/exception"
5
5
  require "devise_saml_authenticatable/logger"
6
6
  require "devise_saml_authenticatable/routes"
7
7
  require "devise_saml_authenticatable/saml_config"
8
+ require "devise_saml_authenticatable/default_attribute_map_resolver"
8
9
  require "devise_saml_authenticatable/default_idp_entity_id_reader"
9
10
 
10
11
  begin
@@ -19,6 +20,10 @@ end
19
20
 
20
21
  # Get saml information from config/saml.yml now
21
22
  module Devise
23
+ # Allow route customization to avoid collision
24
+ mattr_accessor :saml_route_helper_prefix
25
+ @@saml_route_helper_prefix
26
+
22
27
  # Allow logging
23
28
  mattr_accessor :saml_logger
24
29
  @@saml_logger = true
@@ -62,11 +67,23 @@ module Devise
62
67
  mattr_accessor :saml_relay_state
63
68
  @@saml_relay_state
64
69
 
70
+ # Instead of storing the attribute_map in attribute-map.yml, store it in the database, or set it programatically
71
+ mattr_accessor :saml_attribute_map_resolver
72
+ @@saml_attribute_map_resolver ||= ::DeviseSamlAuthenticatable::DefaultAttributeMapResolver
73
+
65
74
  # Implements a #validate method that takes the retrieved resource and response right after retrieval,
66
75
  # and returns true if it's valid. False will cause authentication to fail.
76
+ # Only one of saml_resource_validator and saml_resource_validator_hook may be used.
67
77
  mattr_accessor :saml_resource_validator
68
78
  @@saml_resource_validator
69
79
 
80
+ # Proc that determines whether a technically correct SAML response is valid per some custom logic.
81
+ # Receives the user object (or nil, if no match was found), decorated saml_response and
82
+ # auth_value, inspects the combination for acceptability of login (or create+login, if enabled),
83
+ # and returns true if it's valid. False will cause authentication to fail.
84
+ mattr_accessor :saml_resource_validator_hook
85
+ @@saml_resource_validator_hook
86
+
70
87
  # Custom value for ruby-saml allowed_clock_drift
71
88
  mattr_accessor :allowed_clock_drift_in_seconds
72
89
  @@allowed_clock_drift_in_seconds
@@ -94,7 +111,7 @@ module Devise
94
111
  end
95
112
 
96
113
  # Proc that is called if Devise.saml_update_user and/or Devise.saml_create_user are true.
97
- # Recieves the user object, saml_response and auth_value, and defines how the object's values are
114
+ # Receives the user object, saml_response and auth_value, and defines how the object's values are
98
115
  # updated with regards to the SAML response. See saml_default_update_resource_hook for an example.
99
116
  mattr_accessor :saml_update_resource_hook
100
117
  @@saml_update_resource_hook = @@saml_default_update_resource_hook
@@ -107,11 +124,19 @@ module Devise
107
124
  end
108
125
 
109
126
  # Proc that is called to resolve the saml_response and auth_value into the correct user object.
110
- # Recieves a copy of the ActiveRecord::Model, saml_response and auth_value. Is expected to return
127
+ # Receives a copy of the ActiveRecord::Model, saml_response and auth_value. Is expected to return
111
128
  # one instance of the provided model that is the matched account, or nil if none exists.
112
129
  # See saml_default_resource_locator above for an example.
113
130
  mattr_accessor :saml_resource_locator
114
131
  @@saml_resource_locator = @@saml_default_resource_locator
132
+
133
+ # Proc that is called to resolve the name identifier to use in a LogoutRequest for the current user.
134
+ # Receives the logged-in user.
135
+ # Is expected to return the identifier the IdP understands for this user, e.g. email address or username.
136
+ mattr_accessor :saml_name_identifier_retriever
137
+ @@saml_name_identifier_retriever = Proc.new do |current_user|
138
+ current_user.public_send(Devise.saml_default_user_key)
139
+ end
115
140
  end
116
141
 
117
142
  # Add saml_authenticatable strategy to defaults.