devise_saml_authenticatable 1.9.0 → 2.0.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +10 -25
- data/.ruby-version +1 -1
- data/Gemfile +6 -12
- data/README.md +19 -13
- data/app/controllers/devise/saml_sessions_controller.rb +4 -3
- data/devise_saml_authenticatable.gemspec +3 -2
- data/lib/devise_saml_authenticatable/model.rb +3 -24
- data/lib/devise_saml_authenticatable/saml_config.rb +1 -1
- data/lib/devise_saml_authenticatable/strategy.rb +3 -1
- data/lib/devise_saml_authenticatable/version.rb +1 -1
- data/lib/devise_saml_authenticatable.rb +4 -4
- data/spec/controllers/devise/saml_sessions_controller_spec.rb +17 -14
- data/spec/devise_saml_authenticatable/model_spec.rb +30 -30
- data/spec/devise_saml_authenticatable/saml_config_spec.rb +12 -12
- data/spec/devise_saml_authenticatable/strategy_spec.rb +21 -7
- data/spec/features/saml_authentication_spec.rb +9 -2
- data/spec/rails_helper.rb +14 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/support/{Gemfile.rails5.2 → Gemfile.rails7.1} +7 -3
- data/spec/support/{Gemfile.rails6 → Gemfile.rails7.2} +7 -7
- data/spec/support/Gemfile.rails8.0 +18 -0
- data/spec/support/idp_settings_adapter.rb.erb +1 -1
- data/spec/support/idp_template.rb +3 -7
- data/spec/support/rails_app.rb +6 -4
- data/spec/support/saml_idp_controller.rb.erb +5 -8
- data/spec/support/sp_template.rb +7 -15
- metadata +14 -13
- data/spec/support/Gemfile.rails6.1 +0 -24
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e861297bd4cb5df8bb43ec4aec39496fd5af27ad26ab80c0313ef5005159929e
|
|
4
|
+
data.tar.gz: 6e7199213c9e79ad65fb55581f862eedc9ca5093215e36509d3a6872debdefc4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c0eb3bc7144986fab5d45c7a44c0abf949e7ca004af03c81c6c852e4f505d9cfa29051a5b338e1907a21d5d4c2d239c059f2645e270813efcc61140d43918d20
|
|
7
|
+
data.tar.gz: 61690adf342117a247eea96b0430920b97d8c551c1fe36d84eea449998cb69ee3b7eb295fa669603381f65cff54f887622c042f53fd0a5a54140debe5d1fba62
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -2,9 +2,11 @@ name: ci
|
|
|
2
2
|
on:
|
|
3
3
|
push:
|
|
4
4
|
branches:
|
|
5
|
+
- 1.x-maintenance
|
|
5
6
|
- master
|
|
6
7
|
pull_request:
|
|
7
8
|
branches:
|
|
9
|
+
- 1.x-maintenance
|
|
8
10
|
- master
|
|
9
11
|
jobs:
|
|
10
12
|
test:
|
|
@@ -12,39 +14,22 @@ jobs:
|
|
|
12
14
|
fail-fast: false
|
|
13
15
|
matrix:
|
|
14
16
|
ruby:
|
|
15
|
-
- "3.
|
|
16
|
-
- "3.
|
|
17
|
-
- "2
|
|
18
|
-
- "2.6"
|
|
17
|
+
- "3.4"
|
|
18
|
+
- "3.3"
|
|
19
|
+
- "3.2"
|
|
19
20
|
gemfile:
|
|
20
21
|
- Gemfile
|
|
21
|
-
- spec/support/Gemfile.
|
|
22
|
-
- spec/support/Gemfile.
|
|
23
|
-
- spec/support/Gemfile.rails5.2
|
|
22
|
+
- spec/support/Gemfile.rails7.1
|
|
23
|
+
- spec/support/Gemfile.rails7.2
|
|
24
24
|
bundler:
|
|
25
25
|
- "2"
|
|
26
|
-
exclude:
|
|
27
|
-
- ruby: "2.6"
|
|
28
|
-
gemfile: Gemfile
|
|
29
|
-
bundler: "2"
|
|
30
|
-
- ruby: "3.0"
|
|
31
|
-
gemfile: spec/support/Gemfile.rails5.2
|
|
32
|
-
bundler: "2"
|
|
33
|
-
- ruby: "3.0"
|
|
34
|
-
gemfile: spec/support/Gemfile.rails6
|
|
35
|
-
bundler: "2"
|
|
36
|
-
- ruby: "3.1"
|
|
37
|
-
gemfile: spec/support/Gemfile.rails5.2
|
|
38
|
-
bundler: "2"
|
|
39
|
-
- ruby: "3.1"
|
|
40
|
-
gemfile: spec/support/Gemfile.rails6
|
|
41
|
-
bundler: "2"
|
|
42
26
|
runs-on: ubuntu-latest
|
|
43
27
|
env:
|
|
44
28
|
BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}
|
|
45
29
|
steps:
|
|
46
|
-
- uses: actions/checkout@
|
|
47
|
-
-
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- name: Set up Ruby
|
|
32
|
+
uses: ruby/setup-ruby@v1
|
|
48
33
|
with:
|
|
49
34
|
bundler: ${{ matrix.bundler }}
|
|
50
35
|
ruby-version: ${{ matrix.ruby }}
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.3.7
|
data/Gemfile
CHANGED
|
@@ -6,19 +6,13 @@ gemspec
|
|
|
6
6
|
group :test do
|
|
7
7
|
gem 'rake'
|
|
8
8
|
gem 'rspec', '~> 3.0'
|
|
9
|
-
gem 'rails', '~>
|
|
9
|
+
gem 'rails', '~> 8.0.0'
|
|
10
10
|
gem 'rspec-rails'
|
|
11
|
-
gem 'sqlite3', '~>
|
|
11
|
+
gem 'sqlite3', '~> 2.6.0'
|
|
12
12
|
gem 'capybara'
|
|
13
13
|
gem 'selenium-webdriver'
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if Gem::Version.new(RUBY_VERSION.dup) >= Gem::Version.new("3.1")
|
|
20
|
-
gem 'net-smtp', require: false
|
|
21
|
-
gem 'net-imap', require: false
|
|
22
|
-
gem 'net-pop', require: false
|
|
23
|
-
end
|
|
14
|
+
gem 'webrick'
|
|
15
|
+
gem 'net-smtp', require: false
|
|
16
|
+
gem 'net-imap', require: false
|
|
17
|
+
gem 'net-pop', require: false
|
|
24
18
|
end
|
data/README.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
[](https://github.com/apokalipto/devise_saml_authenticatable/actions/workflows/ci.yml)
|
|
2
2
|
# DeviseSamlAuthenticatable
|
|
3
3
|
|
|
4
4
|
Devise Saml Authenticatable is a Single-Sign-On authentication strategy for devise that relies on SAML.
|
|
5
5
|
It uses [ruby-saml][] to handle all SAML-related stuff.
|
|
6
6
|
|
|
7
|
+
> [!WARNING]
|
|
8
|
+
> The master branch now represents v2.x of this gem, which is still unreleased.
|
|
9
|
+
> See [the 1.x branch README](https://github.com/apokalipto/devise_saml_authenticatable/tree/refs/heads/1.x-maintenance?tab=readme-ov-file) for details about that version.
|
|
10
|
+
|
|
7
11
|
## Installation
|
|
8
12
|
|
|
9
13
|
Add this gem to your application's Gemfile:
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
gem "devise_saml_authenticatable", github: "apokalipto/devise_saml_authenticatable"
|
|
15
|
+
gem "devise_saml_authenticatable"
|
|
13
16
|
|
|
14
17
|
And then execute:
|
|
15
18
|
|
|
@@ -87,7 +90,7 @@ In `config/initializers/devise.rb`:
|
|
|
87
90
|
|
|
88
91
|
# Lambda that is called if Devise.saml_update_user and/or Devise.saml_create_user are true.
|
|
89
92
|
# Receives the model object, saml_response and auth_value, and defines how the object's values are
|
|
90
|
-
# updated with regards to the SAML response.
|
|
93
|
+
# updated with regards to the SAML response.
|
|
91
94
|
# config.saml_update_resource_hook = -> (user, saml_response, auth_value) {
|
|
92
95
|
# saml_response.attributes.resource_keys.each do |key|
|
|
93
96
|
# user.send "#{key}=", saml_response.attribute_value_by_resource_key(key)
|
|
@@ -104,17 +107,17 @@ In `config/initializers/devise.rb`:
|
|
|
104
107
|
# Receives a copy of the ActiveRecord::Model, saml_response and auth_value. Is expected to return
|
|
105
108
|
# one instance of the provided model that is the matched account, or nil if none exists.
|
|
106
109
|
# config.saml_resource_locator = -> (model, saml_response, auth_value) {
|
|
107
|
-
# model.
|
|
110
|
+
# model.find_by(Devise.saml_default_user_key => auth_value)
|
|
108
111
|
# }
|
|
109
|
-
|
|
112
|
+
|
|
110
113
|
|
|
111
114
|
# Set the default user key. The user will be looked up by this key. Make
|
|
112
115
|
# sure that the Authentication Response includes the attribute.
|
|
113
116
|
config.saml_default_user_key = :email
|
|
114
117
|
|
|
115
|
-
# Optional. This stores the session index defined by the IDP during login.
|
|
116
|
-
#
|
|
117
|
-
config.saml_session_index_key = :
|
|
118
|
+
# Optional. This stores the session index defined by the IDP during login.
|
|
119
|
+
# If provided it will be used to facilitate an IDP initiated logout request.
|
|
120
|
+
config.saml_session_index_key = :saml_session_index
|
|
118
121
|
|
|
119
122
|
# You can set this value to use Subject or SAML assertion as info to which email will be compared.
|
|
120
123
|
# If you don't set it then email will be extracted from SAML assertion attributes.
|
|
@@ -151,7 +154,7 @@ In `config/initializers/devise.rb`:
|
|
|
151
154
|
settings.assertion_consumer_service_url = "http://localhost:3000/users/saml/auth"
|
|
152
155
|
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
|
153
156
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
|
154
|
-
settings.
|
|
157
|
+
settings.sp_entity_id = "http://localhost:3000/saml/metadata"
|
|
155
158
|
settings.authn_context = ""
|
|
156
159
|
settings.idp_slo_service_url = "http://localhost/simplesaml/www/saml2/idp/SingleLogoutService.php"
|
|
157
160
|
settings.idp_sso_service_url = "http://localhost/simplesaml/www/saml2/idp/SSOService.php"
|
|
@@ -225,6 +228,9 @@ If you only have one IdP, you can use the config file above, or just return a si
|
|
|
225
228
|
end
|
|
226
229
|
```
|
|
227
230
|
|
|
231
|
+
If you are mapping authorisation *groups* or any other array of values as some providers render (ie: Okta), be aware of [ruby-saml's `single_value_compatibility`](https://github.com/SAML-Toolkits/ruby-saml#retrieving-attributes).
|
|
232
|
+
|
|
233
|
+
|
|
228
234
|
## IdP Settings Adapter
|
|
229
235
|
|
|
230
236
|
Implementing a custom settings adapter allows you to support multiple Identity Providers, and dynamic application domains with the request object.
|
|
@@ -240,7 +246,7 @@ class IdPSettingsAdapter
|
|
|
240
246
|
assertion_consumer_service_url: "#{request.protocol}#{request.host_with_port}/users/saml/auth",
|
|
241
247
|
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
|
242
248
|
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
|
243
|
-
|
|
249
|
+
sp_entity_id: "#{request.protocol}#{request.host_with_port}/saml/metadata",
|
|
244
250
|
idp_entity_id: "http://www.example_idp_entity_id.com",
|
|
245
251
|
authn_context: "",
|
|
246
252
|
idp_slo_service_url: "http://example_idp_slo_service_url.com",
|
|
@@ -252,7 +258,7 @@ class IdPSettingsAdapter
|
|
|
252
258
|
assertion_consumer_service_url: "http://localhost:3000/users/saml/auth",
|
|
253
259
|
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
|
254
260
|
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
|
255
|
-
|
|
261
|
+
sp_entity_id: "http://localhost:3000/saml/metadata",
|
|
256
262
|
idp_entity_id: "http://www.another_idp_entity_id.biz",
|
|
257
263
|
authn_context: "",
|
|
258
264
|
idp_slo_service_url: "http://another_idp_slo_service_url.com",
|
|
@@ -297,7 +303,7 @@ Logout support is included by immediately terminating the local session and then
|
|
|
297
303
|
|
|
298
304
|
Logout requests from the IDP are supported by the `idp_sign_out` endpoint. Directing logout requests to `users/saml/idp_sign_out` will log out the respective user by invalidating their current sessions.
|
|
299
305
|
|
|
300
|
-
|
|
306
|
+
To disable this feature, set `saml_session_index_key` to `nil`.
|
|
301
307
|
|
|
302
308
|
## Signing and Encrypting Authentication Requests and Assertions
|
|
303
309
|
|
|
@@ -23,10 +23,11 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
|
23
23
|
|
|
24
24
|
def idp_sign_out
|
|
25
25
|
if params[:SAMLRequest] && Devise.saml_session_index_key
|
|
26
|
+
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
|
|
27
|
+
session[Devise.saml_session_index_key] = nil
|
|
28
|
+
|
|
26
29
|
saml_config = saml_config(get_idp_entity_id(params), request)
|
|
27
30
|
logout_request = OneLogin::RubySaml::SloLogoutrequest.new(params[:SAMLRequest], settings: saml_config)
|
|
28
|
-
resource_class.reset_session_key_for(logout_request.name_id)
|
|
29
|
-
|
|
30
31
|
redirect_to generate_idp_logout_response(saml_config, logout_request.id), allow_other_host: true
|
|
31
32
|
elsif params[:SAMLResponse]
|
|
32
33
|
# Currently Devise handles the session invalidation when the request is made.
|
|
@@ -56,7 +57,7 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
|
56
57
|
|
|
57
58
|
@name_identifier_value_for_sp_initiated_logout = Devise.saml_name_identifier_retriever.call(current_user)
|
|
58
59
|
if Devise.saml_session_index_key
|
|
59
|
-
@sessionindex_for_sp_initiated_logout =
|
|
60
|
+
@sessionindex_for_sp_initiated_logout = session[Devise.saml_session_index_key]
|
|
60
61
|
end
|
|
61
62
|
end
|
|
62
63
|
|
|
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
|
6
6
|
gem.email = ["Josef.Sauter@gmail.com"]
|
|
7
7
|
gem.description = %q{SAML Authentication for devise}
|
|
8
8
|
gem.summary = %q{SAML Authentication for devise }
|
|
9
|
-
gem.homepage = ""
|
|
9
|
+
gem.homepage = "https://github.com/apokalipto/devise_saml_authenticatable"
|
|
10
10
|
gem.license = "MIT"
|
|
11
11
|
|
|
12
12
|
gem.files = `git ls-files`.split($\)
|
|
@@ -16,7 +16,8 @@ Gem::Specification.new do |gem|
|
|
|
16
16
|
gem.require_paths = ["lib"]
|
|
17
17
|
gem.version = DeviseSamlAuthenticatable::VERSION
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
|
19
|
+
gem.required_ruby_version = ">= 2.6.0"
|
|
19
20
|
|
|
20
21
|
gem.add_dependency("devise","> 2.0.0")
|
|
21
|
-
gem.add_dependency("ruby-saml","~> 1.
|
|
22
|
+
gem.add_dependency("ruby-saml","~> 1.18")
|
|
22
23
|
end
|
|
@@ -12,22 +12,6 @@ module Devise
|
|
|
12
12
|
attr_accessor :password_confirmation
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
def after_saml_authentication(session_index)
|
|
16
|
-
if Devise.saml_session_index_key && self.respond_to?(Devise.saml_session_index_key)
|
|
17
|
-
self.update_attribute(Devise.saml_session_index_key, session_index)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def authenticatable_salt
|
|
22
|
-
if Devise.saml_session_index_key &&
|
|
23
|
-
self.respond_to?(Devise.saml_session_index_key) &&
|
|
24
|
-
self.send(Devise.saml_session_index_key).present?
|
|
25
|
-
self.send(Devise.saml_session_index_key)
|
|
26
|
-
else
|
|
27
|
-
super
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
15
|
module ClassMethods
|
|
32
16
|
def authenticate_with_saml(saml_response, relay_state)
|
|
33
17
|
key = Devise.saml_default_user_key
|
|
@@ -50,7 +34,7 @@ module Devise
|
|
|
50
34
|
else Devise.saml_resource_validator_hook.call(resource, decorated_response, auth_value)
|
|
51
35
|
end
|
|
52
36
|
if !valid
|
|
53
|
-
logger.info("
|
|
37
|
+
logger.info("#{self.name}(#{auth_value}) did not pass custom validation.")
|
|
54
38
|
return nil
|
|
55
39
|
end
|
|
56
40
|
end
|
|
@@ -60,10 +44,10 @@ module Devise
|
|
|
60
44
|
end
|
|
61
45
|
if resource.nil?
|
|
62
46
|
if create_user
|
|
63
|
-
logger.info("Creating
|
|
47
|
+
logger.info("Creating #{self.name.downcase}(#{auth_value}).")
|
|
64
48
|
resource = new
|
|
65
49
|
else
|
|
66
|
-
logger.info("
|
|
50
|
+
logger.info("#{self.name}(#{auth_value}) not found. Not configured to create the #{self.name.downcase}.")
|
|
67
51
|
return nil
|
|
68
52
|
end
|
|
69
53
|
end
|
|
@@ -78,11 +62,6 @@ module Devise
|
|
|
78
62
|
resource
|
|
79
63
|
end
|
|
80
64
|
|
|
81
|
-
def reset_session_key_for(name_id)
|
|
82
|
-
resource = find_by(Devise.saml_default_user_key => name_id)
|
|
83
|
-
resource.update_attribute(Devise.saml_session_index_key, nil) unless resource.nil?
|
|
84
|
-
end
|
|
85
|
-
|
|
86
65
|
def find_for_shibb_authentication(conditions)
|
|
87
66
|
find_for_authentication(conditions)
|
|
88
67
|
end
|
|
@@ -14,7 +14,7 @@ module DeviseSamlAuthenticatable
|
|
|
14
14
|
return @file_based_config if @file_based_config
|
|
15
15
|
idp_config_path = "#{Rails.root}/config/idp.yml"
|
|
16
16
|
|
|
17
|
-
if File.
|
|
17
|
+
if File.exist?(idp_config_path)
|
|
18
18
|
@file_based_config ||= OneLogin::RubySaml::Settings.new(YAML.load(File.read(idp_config_path))[Rails.env])
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -19,7 +19,9 @@ module Devise
|
|
|
19
19
|
parse_saml_response
|
|
20
20
|
retrieve_resource unless self.halted?
|
|
21
21
|
unless self.halted?
|
|
22
|
-
|
|
22
|
+
if Devise.saml_session_index_key
|
|
23
|
+
request.session[Devise.saml_session_index_key] = @response.sessionindex
|
|
24
|
+
end
|
|
23
25
|
success!(@resource)
|
|
24
26
|
end
|
|
25
27
|
end
|
|
@@ -30,7 +30,7 @@ module Devise
|
|
|
30
30
|
|
|
31
31
|
# Add valid users to database
|
|
32
32
|
# Can accept a Boolean value or a Proc that is called with the model class, the saml_response and auth_value
|
|
33
|
-
# Ex:
|
|
33
|
+
# Ex:
|
|
34
34
|
# Devise.saml_create_user = Proc.new do |model_class, saml_response, auth_value|
|
|
35
35
|
# model_class == Admin
|
|
36
36
|
# end
|
|
@@ -39,7 +39,7 @@ module Devise
|
|
|
39
39
|
|
|
40
40
|
# Update user attributes after login
|
|
41
41
|
# Can accept a Boolean value or a Proc that is called with the model class, the saml_response and auth_value
|
|
42
|
-
# Ex:
|
|
42
|
+
# Ex:
|
|
43
43
|
# Devise.saml_update_user = Proc.new do |model_class, saml_response, auth_value|
|
|
44
44
|
# model_class == User
|
|
45
45
|
# end
|
|
@@ -54,7 +54,7 @@ module Devise
|
|
|
54
54
|
|
|
55
55
|
# Key used to index sessions for later retrieval
|
|
56
56
|
mattr_accessor :saml_session_index_key
|
|
57
|
-
@@saml_session_index_key
|
|
57
|
+
@@saml_session_index_key ||= :saml_session_index
|
|
58
58
|
|
|
59
59
|
# Redirect after signout (redirects to 'users/saml/sign_in' by default)
|
|
60
60
|
mattr_accessor :saml_sign_out_success_url
|
|
@@ -134,7 +134,7 @@ module Devise
|
|
|
134
134
|
# See saml_resource_locator for more information.
|
|
135
135
|
mattr_reader :saml_default_resource_locator
|
|
136
136
|
@@saml_default_resource_locator = Proc.new do |model, saml_response, auth_value|
|
|
137
|
-
model.
|
|
137
|
+
model.find_by(Devise.saml_default_user_key => auth_value)
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
# Proc that is called to resolve the saml_response and auth_value into the correct user object.
|
|
@@ -31,6 +31,7 @@ require_relative '../../../app/controllers/devise/saml_sessions_controller'
|
|
|
31
31
|
|
|
32
32
|
describe Devise::SamlSessionsController, type: :controller do
|
|
33
33
|
include RubySamlSupport
|
|
34
|
+
include Devise::Test::ControllerHelpers
|
|
34
35
|
|
|
35
36
|
let(:idp_providers_adapter) { spy('Stub IDPSettings Adaptor') }
|
|
36
37
|
|
|
@@ -40,8 +41,8 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
40
41
|
assertion_consumer_service_url: 'acs_url',
|
|
41
42
|
assertion_consumer_service_binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
|
42
43
|
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
|
|
43
|
-
|
|
44
|
-
idp_entity_id: '
|
|
44
|
+
sp_entity_id: 'sp_issuer',
|
|
45
|
+
idp_entity_id: 'https://www.example.com',
|
|
45
46
|
authn_context: '',
|
|
46
47
|
idp_cert: 'idp_cert'
|
|
47
48
|
}
|
|
@@ -123,7 +124,7 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
123
124
|
end
|
|
124
125
|
|
|
125
126
|
subject(:do_get) do
|
|
126
|
-
get :new, params: { entity_id: '
|
|
127
|
+
get :new, params: { entity_id: 'https://www.example.com' }
|
|
127
128
|
end
|
|
128
129
|
|
|
129
130
|
before do
|
|
@@ -137,7 +138,7 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
137
138
|
|
|
138
139
|
it 'redirects to the associated IdP SSO target url' do
|
|
139
140
|
do_get
|
|
140
|
-
expect(idp_providers_adapter).to have_received(:settings).with('
|
|
141
|
+
expect(idp_providers_adapter).to have_received(:settings).with('https://www.example.com', request)
|
|
141
142
|
expect(response).to redirect_to(%r{\Ahttp://idp_sso_url\?SAMLRequest=})
|
|
142
143
|
end
|
|
143
144
|
end
|
|
@@ -167,7 +168,7 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
167
168
|
settings.assertion_consumer_service_url = 'http://localhost:3000/users/saml/auth'
|
|
168
169
|
settings.assertion_consumer_service_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
|
169
170
|
settings.name_identifier_format = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
|
|
170
|
-
settings.
|
|
171
|
+
settings.sp_entity_id = 'http://localhost:3000'
|
|
171
172
|
end
|
|
172
173
|
end
|
|
173
174
|
|
|
@@ -256,7 +257,8 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
256
257
|
end
|
|
257
258
|
|
|
258
259
|
it 'includes a LogoutRequest with the name identifier and session index', :aggregate_failures do
|
|
259
|
-
controller.current_user = Struct.new(:email
|
|
260
|
+
controller.current_user = Struct.new(:email).new('user@example.com')
|
|
261
|
+
session[Devise.saml_session_index_key] = 'sessionindex'
|
|
260
262
|
|
|
261
263
|
actual_settings = nil
|
|
262
264
|
expect_any_instance_of(OneLogin::RubySaml::Logoutrequest).to receive(:create) do |_, settings|
|
|
@@ -290,7 +292,7 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
290
292
|
end
|
|
291
293
|
|
|
292
294
|
subject(:do_delete) do
|
|
293
|
-
delete :destroy, params: { entity_id: '
|
|
295
|
+
delete :destroy, params: { entity_id: 'https://www.example.com' }
|
|
294
296
|
end
|
|
295
297
|
|
|
296
298
|
before do
|
|
@@ -305,7 +307,7 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
305
307
|
it 'redirects to the associated IdP SLO target url' do
|
|
306
308
|
do_delete
|
|
307
309
|
expect(controller).to have_received(:sign_out)
|
|
308
|
-
expect(idp_providers_adapter).to have_received(:settings).with('
|
|
310
|
+
expect(idp_providers_adapter).to have_received(:settings).with('https://www.example.com', request)
|
|
309
311
|
expect(response).to redirect_to(%r{\Ahttp://idp_slo_url\?SAMLRequest=})
|
|
310
312
|
end
|
|
311
313
|
end
|
|
@@ -322,9 +324,10 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
322
324
|
end
|
|
323
325
|
|
|
324
326
|
it 'returns invalid request if SAMLRequest or SAMLResponse is not passed' do
|
|
325
|
-
|
|
327
|
+
session[Devise.saml_session_index_key] = 'sessionindex'
|
|
326
328
|
post :idp_sign_out
|
|
327
329
|
expect(response.status).to eq 500
|
|
330
|
+
expect(session[Devise.saml_session_index_key]).to eq('sessionindex')
|
|
328
331
|
end
|
|
329
332
|
|
|
330
333
|
context 'when receiving a logout response from the IdP after redirecting an SP logout request' do
|
|
@@ -361,23 +364,23 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
361
364
|
double(:slo_logoutrequest, {
|
|
362
365
|
id: 42,
|
|
363
366
|
name_id: name_id,
|
|
364
|
-
issuer: '
|
|
367
|
+
issuer: 'https://www.example.com'
|
|
365
368
|
})
|
|
366
369
|
end
|
|
367
370
|
let(:name_id) { '12312312' }
|
|
368
371
|
before do
|
|
369
372
|
allow(OneLogin::RubySaml::SloLogoutrequest).to receive(:new).and_return(saml_request)
|
|
370
|
-
|
|
373
|
+
session[Devise.saml_session_index_key] = 'sessionindex'
|
|
371
374
|
end
|
|
372
375
|
|
|
373
376
|
it 'direct the resource to reset the session key' do
|
|
374
377
|
do_post
|
|
375
378
|
expect(response).to redirect_to response_url
|
|
376
|
-
expect(
|
|
379
|
+
expect(session[Devise.saml_session_index_key]).to be_nil
|
|
377
380
|
end
|
|
378
381
|
|
|
379
382
|
context 'with a specified idp' do
|
|
380
|
-
let(:idp_entity_id) { '
|
|
383
|
+
let(:idp_entity_id) { 'https://www.example.com' }
|
|
381
384
|
before do
|
|
382
385
|
Devise.idp_settings_adapter = idp_providers_adapter
|
|
383
386
|
end
|
|
@@ -387,6 +390,7 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
387
390
|
expect(response.status).to eq 302
|
|
388
391
|
expect(idp_providers_adapter).to have_received(:settings).with(idp_entity_id, request)
|
|
389
392
|
expect(response).to redirect_to 'http://localhost/logout_response'
|
|
393
|
+
expect(session[Devise.saml_session_index_key]).to be_nil
|
|
390
394
|
end
|
|
391
395
|
end
|
|
392
396
|
|
|
@@ -407,7 +411,6 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
|
407
411
|
end
|
|
408
412
|
|
|
409
413
|
it 'returns invalid request' do
|
|
410
|
-
expect(User).not_to receive(:reset_session_key_for).with(name_id)
|
|
411
414
|
do_post
|
|
412
415
|
expect(response.status).to eq 500
|
|
413
416
|
end
|