devise_saml_authenticatable 1.6.3 → 1.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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +76 -0
- data/README.md +12 -8
- data/app/controllers/devise/saml_sessions_controller.rb +17 -2
- data/lib/devise_saml_authenticatable/strategy.rb +14 -4
- data/lib/devise_saml_authenticatable/version.rb +1 -1
- data/lib/devise_saml_authenticatable.rb +4 -0
- data/spec/controllers/devise/saml_sessions_controller_spec.rb +142 -54
- data/spec/devise_saml_authenticatable/saml_config_spec.rb +64 -17
- data/spec/devise_saml_authenticatable/strategy_spec.rb +54 -5
- data/spec/support/Gemfile.rails5.2 +1 -1
- data/spec/support/Gemfile.rails6 +14 -0
- data/spec/support/idp_settings_adapter.rb.erb +19 -9
- data/spec/support/rails_app.rb +5 -6
- data/spec/support/ruby_saml_support.rb +10 -0
- data/spec/support/sp_template.rb +15 -3
- metadata +8 -4
- data/.travis.yml +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 23fdb33308c8d98c67e3fe7d5654bfcdc7afe40c2276822a3936785ed29e15ea
|
4
|
+
data.tar.gz: 11569096a198fb51b129d82eaab03a870c3c8983b7dfe88aa0bcc53f1f4fa2ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 605f76c64fa08cb1ec9f26224af74ccec6c8d85b507899e6f61f1c65e8ada6b7672b6b9398d78fcfbd075d8c7754e824e0a8ed822001b124a6658e862b72203c
|
7
|
+
data.tar.gz: 0f8bb1f715288790cffb1b20214d6c0da71c546aaa09e626183b86d1274c5d6e3aae90dea8af6c4d572c6f2131360c948203a9a14706ed7414c685833eac173d
|
@@ -0,0 +1,76 @@
|
|
1
|
+
name: ci
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
pull_request:
|
7
|
+
branches:
|
8
|
+
- master
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
strategy:
|
12
|
+
fail-fast: false
|
13
|
+
matrix:
|
14
|
+
ruby:
|
15
|
+
- "2.7"
|
16
|
+
- "2.6"
|
17
|
+
- "2.5"
|
18
|
+
- "2.4"
|
19
|
+
- "2.3"
|
20
|
+
gemfile:
|
21
|
+
- Gemfile
|
22
|
+
- spec/support/Gemfile.rails6
|
23
|
+
- spec/support/Gemfile.rails5.2
|
24
|
+
- spec/support/Gemfile.rails5.1
|
25
|
+
- spec/support/Gemfile.rails5
|
26
|
+
bundler:
|
27
|
+
- "2"
|
28
|
+
exclude:
|
29
|
+
- ruby: "2.3"
|
30
|
+
gemfile: Gemfile
|
31
|
+
bundler: "2"
|
32
|
+
- ruby: "2.3"
|
33
|
+
gemfile: spec/support/Gemfile.rails6
|
34
|
+
bundler: "2"
|
35
|
+
- ruby: "2.4"
|
36
|
+
gemfile: Gemfile
|
37
|
+
bundler: "2"
|
38
|
+
- ruby: "2.4"
|
39
|
+
gemfile: spec/support/Gemfile.rails6
|
40
|
+
bundler: "2"
|
41
|
+
include:
|
42
|
+
- ruby: "2.5"
|
43
|
+
gemfile: spec/support/Gemfile.rails4
|
44
|
+
bundler: "1"
|
45
|
+
- ruby: "2.4"
|
46
|
+
gemfile: spec/support/Gemfile.rails4
|
47
|
+
bundler: "1"
|
48
|
+
- ruby: "2.3"
|
49
|
+
gemfile: spec/support/Gemfile.rails4
|
50
|
+
bundler: "1"
|
51
|
+
- ruby: "2.2"
|
52
|
+
gemfile: spec/support/Gemfile.rails5.1
|
53
|
+
bundler: "1"
|
54
|
+
- ruby: "2.2"
|
55
|
+
gemfile: spec/support/Gemfile.rails5
|
56
|
+
bundler: "1"
|
57
|
+
- ruby: "2.2"
|
58
|
+
gemfile: spec/support/Gemfile.rails4
|
59
|
+
bundler: "1"
|
60
|
+
- ruby: "2.1"
|
61
|
+
gemfile: spec/support/Gemfile.rails4
|
62
|
+
bundler: "1"
|
63
|
+
- ruby: "2.0"
|
64
|
+
gemfile: spec/support/Gemfile.rails4
|
65
|
+
bundler: "1"
|
66
|
+
runs-on: ubuntu-latest
|
67
|
+
env:
|
68
|
+
BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}
|
69
|
+
steps:
|
70
|
+
- uses: actions/checkout@v2
|
71
|
+
- uses: ruby/setup-ruby@v1
|
72
|
+
with:
|
73
|
+
bundler: ${{ matrix.bundler }}
|
74
|
+
ruby-version: ${{ matrix.ruby }}
|
75
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
76
|
+
- run: bundle exec rake
|
data/README.md
CHANGED
@@ -57,8 +57,8 @@ An extra step in SAML SSO setup is adding your application to your identity prov
|
|
57
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
58
|
|
59
59
|
- Issuer (`idp_entity_id`)
|
60
|
-
- SSO endpoint (`
|
61
|
-
- SLO endpoint (`
|
60
|
+
- SSO endpoint (`idp_sso_service_url`)
|
61
|
+
- SLO endpoint (`idp_slo_service_url`)
|
62
62
|
- Certificate fingerprint (`idp_cert_fingerprint`) and algorithm (`idp_cert_fingerprint_algorithm`)
|
63
63
|
- Or the certificate itself (`idp_cert`)
|
64
64
|
|
@@ -111,6 +111,10 @@ In `config/initializers/devise.rb`:
|
|
111
111
|
# This is a time in seconds.
|
112
112
|
# config.allowed_clock_drift_in_seconds = 0
|
113
113
|
|
114
|
+
# In SAML responses, validate that the identity provider has included an InResponseTo
|
115
|
+
# header that matches the ID of the SAML request. (Default is false)
|
116
|
+
# config.saml_validate_in_response_to = false
|
117
|
+
|
114
118
|
# Configure with your SAML settings (see ruby-saml's README for more information: https://github.com/onelogin/ruby-saml).
|
115
119
|
config.saml_configure do |settings|
|
116
120
|
# assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
|
@@ -119,8 +123,8 @@ In `config/initializers/devise.rb`:
|
|
119
123
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
120
124
|
settings.issuer = "http://localhost:3000/saml/metadata"
|
121
125
|
settings.authn_context = ""
|
122
|
-
settings.
|
123
|
-
settings.
|
126
|
+
settings.idp_slo_service_url = "http://localhost/simplesaml/www/saml2/idp/SingleLogoutService.php"
|
127
|
+
settings.idp_sso_service_url = "http://localhost/simplesaml/www/saml2/idp/SSOService.php"
|
124
128
|
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
129
|
settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
|
126
130
|
end
|
@@ -207,8 +211,8 @@ class IdPSettingsAdapter
|
|
207
211
|
issuer: "http://localhost:3000/saml/metadata",
|
208
212
|
idp_entity_id: "http://www.example_idp_entity_id.com",
|
209
213
|
authn_context: "",
|
210
|
-
|
211
|
-
|
214
|
+
idp_slo_service_url: "http://example_idp_slo_service_url.com",
|
215
|
+
idp_sso_service_url: "http://example_idp_sso_service_url.com",
|
212
216
|
idp_cert: "example_idp_cert"
|
213
217
|
}
|
214
218
|
when "http://www.another_idp_entity_id.biz"
|
@@ -219,8 +223,8 @@ class IdPSettingsAdapter
|
|
219
223
|
issuer: "http://localhost:3000/saml/metadata",
|
220
224
|
idp_entity_id: "http://www.another_idp_entity_id.biz",
|
221
225
|
authn_context: "",
|
222
|
-
|
223
|
-
|
226
|
+
idp_slo_service_url: "http://another_idp_slo_service_url.com",
|
227
|
+
idp_sso_service_url: "http://another_idp_sso_service_url.com",
|
224
228
|
idp_cert: "another_idp_cert"
|
225
229
|
}
|
226
230
|
else
|
@@ -5,10 +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
|
+
prepend_before_filter :verify_signed_out_user, :store_info_for_sp_initiated_logout, only: :destroy
|
9
9
|
else
|
10
10
|
skip_before_action :verify_authenticity_token, raise: false
|
11
|
-
prepend_before_action :store_info_for_sp_initiated_logout, only: :destroy
|
11
|
+
prepend_before_action :verify_signed_out_user, :store_info_for_sp_initiated_logout, only: :destroy
|
12
12
|
end
|
13
13
|
|
14
14
|
def new
|
@@ -16,6 +16,9 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
16
16
|
request = OneLogin::RubySaml::Authrequest.new
|
17
17
|
auth_params = { RelayState: relay_state } if relay_state
|
18
18
|
action = request.create(saml_config(idp_entity_id), auth_params || {})
|
19
|
+
if request.respond_to?(:request_id)
|
20
|
+
session[:saml_transaction_id] = request.request_id
|
21
|
+
end
|
19
22
|
redirect_to action
|
20
23
|
end
|
21
24
|
|
@@ -79,6 +82,18 @@ class Devise::SamlSessionsController < Devise::SessionsController
|
|
79
82
|
request.create(saml_settings)
|
80
83
|
end
|
81
84
|
|
85
|
+
# Overried devise: if user is signed out, not create the SP initiated logout request,
|
86
|
+
# redirect to saml_sign_out_success_url,
|
87
|
+
# or devise's after_sign_out_path_for
|
88
|
+
def verify_signed_out_user
|
89
|
+
if all_signed_out?
|
90
|
+
set_flash_message! :notice, :already_signed_out
|
91
|
+
|
92
|
+
redirect_to Devise.saml_sign_out_success_url.presence ||
|
93
|
+
Devise::SessionsController.new.after_sign_out_path_for(resource_name)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
82
97
|
def generate_idp_logout_response(saml_config, logout_request_id)
|
83
98
|
|
84
99
|
params = {}
|
@@ -8,8 +8,7 @@ module Devise
|
|
8
8
|
if params[:SAMLResponse]
|
9
9
|
OneLogin::RubySaml::Response.new(
|
10
10
|
params[:SAMLResponse],
|
11
|
-
|
12
|
-
allowed_clock_drift: Devise.allowed_clock_drift_in_seconds,
|
11
|
+
response_options,
|
13
12
|
)
|
14
13
|
else
|
15
14
|
false
|
@@ -36,8 +35,7 @@ module Devise
|
|
36
35
|
def parse_saml_response
|
37
36
|
@response = OneLogin::RubySaml::Response.new(
|
38
37
|
params[:SAMLResponse],
|
39
|
-
|
40
|
-
allowed_clock_drift: Devise.allowed_clock_drift_in_seconds,
|
38
|
+
response_options,
|
41
39
|
)
|
42
40
|
unless @response.is_valid?
|
43
41
|
failed_auth("Auth errors: #{@response.errors.join(', ')}")
|
@@ -57,6 +55,18 @@ module Devise
|
|
57
55
|
Devise.saml_failed_callback.new.handle(@response, self) if Devise.saml_failed_callback
|
58
56
|
end
|
59
57
|
|
58
|
+
def response_options
|
59
|
+
options = {
|
60
|
+
settings: saml_config(get_idp_entity_id(params)),
|
61
|
+
allowed_clock_drift: Devise.allowed_clock_drift_in_seconds,
|
62
|
+
}
|
63
|
+
|
64
|
+
if Devise.saml_validate_in_response_to
|
65
|
+
options[:matches_request_id] = request.session[:saml_transaction_id] || "ID_MISSING"
|
66
|
+
end
|
67
|
+
|
68
|
+
options
|
69
|
+
end
|
60
70
|
end
|
61
71
|
end
|
62
72
|
end
|
@@ -67,6 +67,10 @@ module Devise
|
|
67
67
|
mattr_accessor :saml_relay_state
|
68
68
|
@@saml_relay_state
|
69
69
|
|
70
|
+
# Validate that the InResponseTo header in SAML responses matches the ID of the request.
|
71
|
+
mattr_accessor :saml_validate_in_response_to
|
72
|
+
@@saml_validate_in_response_to = false
|
73
|
+
|
70
74
|
# Instead of storing the attribute_map in attribute-map.yml, store it in the database, or set it programatically
|
71
75
|
mattr_accessor :saml_attribute_map_resolver
|
72
76
|
@@saml_attribute_map_resolver ||= "::DeviseSamlAuthenticatable::DefaultAttributeMapResolver"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rails_helper'
|
2
|
+
require 'support/ruby_saml_support'
|
2
3
|
|
3
4
|
# The important parts from devise
|
4
5
|
class DeviseController < ApplicationController
|
@@ -8,38 +9,55 @@ class DeviseController < ApplicationController
|
|
8
9
|
User
|
9
10
|
end
|
10
11
|
|
12
|
+
def resource_name
|
13
|
+
"users"
|
14
|
+
end
|
15
|
+
|
11
16
|
def require_no_authentication
|
12
17
|
end
|
18
|
+
|
19
|
+
def set_flash_message!(key, kind, options = {})
|
20
|
+
flash[key] = I18n.t("devise.sessions.#{kind}")
|
21
|
+
end
|
13
22
|
end
|
23
|
+
|
14
24
|
class Devise::SessionsController < DeviseController
|
15
25
|
def destroy
|
16
26
|
sign_out
|
17
27
|
redirect_to after_sign_out_path_for(:user)
|
18
28
|
end
|
19
|
-
|
20
|
-
def verify_signed_out_user
|
21
|
-
# no-op for these tests
|
22
|
-
end
|
23
29
|
end
|
24
30
|
|
25
31
|
require_relative '../../../app/controllers/devise/saml_sessions_controller'
|
26
32
|
|
27
33
|
describe Devise::SamlSessionsController, type: :controller do
|
34
|
+
include RubySamlSupport
|
35
|
+
|
28
36
|
let(:idp_providers_adapter) { spy("Stub IDPSettings Adaptor") }
|
29
37
|
|
30
38
|
before do
|
31
39
|
@request.env["devise.mapping"] = Devise.mappings[:user]
|
32
|
-
|
40
|
+
settings = {
|
33
41
|
assertion_consumer_service_url: "acs_url",
|
34
42
|
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
35
43
|
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
36
44
|
issuer: "sp_issuer",
|
37
45
|
idp_entity_id: "http://www.example.com",
|
38
46
|
authn_context: "",
|
39
|
-
idp_slo_target_url: "http://idp_slo_url",
|
40
|
-
idp_sso_target_url: "http://idp_sso_url",
|
41
47
|
idp_cert: "idp_cert"
|
48
|
+
}
|
49
|
+
with_ruby_saml_1_12_or_greater(proc {
|
50
|
+
settings.merge!(
|
51
|
+
idp_slo_service_url: "http://idp_slo_url",
|
52
|
+
idp_sso_service_url: "http://idp_sso_url",
|
53
|
+
)
|
54
|
+
}, else_do: proc {
|
55
|
+
settings.merge!(
|
56
|
+
idp_slo_target_url: "http://idp_slo_url",
|
57
|
+
idp_sso_target_url: "http://idp_sso_url",
|
58
|
+
)
|
42
59
|
})
|
60
|
+
allow(idp_providers_adapter).to receive(:settings).and_return(settings)
|
43
61
|
end
|
44
62
|
|
45
63
|
before do
|
@@ -72,6 +90,13 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
72
90
|
do_get
|
73
91
|
expect(response).to redirect_to(%r(\Ahttp://localhost:8009/saml/auth\?SAMLRequest=))
|
74
92
|
end
|
93
|
+
|
94
|
+
it "stores saml_transaction_id in the session" do
|
95
|
+
do_get
|
96
|
+
if OneLogin::RubySaml::Authrequest.public_instance_methods.include?(:request_id)
|
97
|
+
expect(session[:saml_transaction_id]).to be_present
|
98
|
+
end
|
99
|
+
end
|
75
100
|
end
|
76
101
|
|
77
102
|
context "with a specified idp" do
|
@@ -84,6 +109,13 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
84
109
|
expect(response).to redirect_to(%r(\Ahttp://idp_sso_url\?SAMLRequest=))
|
85
110
|
end
|
86
111
|
|
112
|
+
it "stores saml_transaction_id in the session" do
|
113
|
+
do_get
|
114
|
+
if OneLogin::RubySaml::Authrequest.public_instance_methods.include?(:request_id)
|
115
|
+
expect(session[:saml_transaction_id]).to be_present
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
87
119
|
it "uses the DefaultIdpEntityIdReader" do
|
88
120
|
expect(DeviseSamlAuthenticatable::DefaultIdpEntityIdReader).to receive(:entity_id)
|
89
121
|
do_get
|
@@ -172,80 +204,136 @@ describe Devise::SamlSessionsController, type: :controller do
|
|
172
204
|
end
|
173
205
|
|
174
206
|
describe '#destroy' do
|
175
|
-
|
176
|
-
allow(controller).to receive(:sign_out)
|
177
|
-
end
|
207
|
+
subject { delete :destroy }
|
178
208
|
|
179
|
-
context "when
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
209
|
+
context "when user is signed out" do
|
210
|
+
before do
|
211
|
+
class Devise::SessionsController < DeviseController
|
212
|
+
def all_signed_out?
|
213
|
+
true
|
214
|
+
end
|
215
|
+
end
|
184
216
|
end
|
185
|
-
end
|
186
217
|
|
187
|
-
|
188
|
-
|
189
|
-
|
218
|
+
shared_examples "not create SP initiated logout request" do
|
219
|
+
it do
|
220
|
+
expect(OneLogin::RubySaml::Logoutrequest).not_to receive(:new)
|
221
|
+
subject
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when Devise.saml_sign_out_success_url is set" do
|
226
|
+
before do
|
227
|
+
allow(Devise).to receive(:saml_sign_out_success_url).and_return("http://localhost:8009/logged_out")
|
228
|
+
end
|
229
|
+
|
230
|
+
it "redirect to saml_sign_out_success_url" do
|
231
|
+
is_expected.to redirect_to "http://localhost:8009/logged_out"
|
232
|
+
expect(flash[:notice]).to eq I18n.t("devise.sessions.already_signed_out")
|
233
|
+
end
|
234
|
+
|
235
|
+
it_behaves_like "not create SP initiated logout request"
|
190
236
|
end
|
191
237
|
|
192
|
-
|
193
|
-
|
238
|
+
context "when Devise.saml_sign_out_success_url is not set" do
|
239
|
+
before do
|
240
|
+
class Devise::SessionsController < DeviseController
|
241
|
+
def after_sign_out_path_for(_)
|
242
|
+
"http://localhost:8009/logged_out"
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
194
246
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
"http://localhost:8009/saml/logout"
|
247
|
+
it "redirect to devise's after sign out path" do
|
248
|
+
is_expected.to redirect_to "http://localhost:8009/logged_out"
|
249
|
+
expect(flash[:notice]).to eq I18n.t("devise.sessions.already_signed_out")
|
199
250
|
end
|
200
251
|
|
201
|
-
|
202
|
-
expect(actual_settings.name_identifier_value).to eq("user@example.com")
|
203
|
-
expect(actual_settings.sessionindex).to eq("sessionindex")
|
252
|
+
it_behaves_like "not create SP initiated logout request"
|
204
253
|
end
|
205
254
|
end
|
206
255
|
|
207
|
-
context "
|
256
|
+
context "when user is not signed out" do
|
208
257
|
before do
|
209
|
-
Devise
|
258
|
+
class Devise::SessionsController < DeviseController
|
259
|
+
def all_signed_out?
|
260
|
+
false
|
261
|
+
end
|
262
|
+
end
|
263
|
+
allow(controller).to receive(:sign_out)
|
210
264
|
end
|
211
265
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
266
|
+
context "when using the default saml config" do
|
267
|
+
it "signs out and redirects to the IdP" do
|
268
|
+
delete :destroy
|
269
|
+
expect(controller).to have_received(:sign_out)
|
270
|
+
expect(response).to redirect_to(%r(\Ahttp://localhost:8009/saml/logout\?SAMLRequest=))
|
271
|
+
end
|
217
272
|
end
|
218
273
|
|
219
|
-
context "
|
220
|
-
|
221
|
-
|
222
|
-
params[:entity_id]
|
223
|
-
end
|
274
|
+
context "when configured to use a non-transient name identifier" do
|
275
|
+
before do
|
276
|
+
allow(Devise.saml_config).to receive(:name_identifier_format).and_return("urn:oasis:names:tc:SAML:2.0:nameid-format:persistent")
|
224
277
|
end
|
225
278
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
279
|
+
it "includes a LogoutRequest with the name identifier and session index", :aggregate_failures do
|
280
|
+
controller.current_user = Struct.new(:email, :session_index).new("user@example.com", "sessionindex")
|
281
|
+
|
282
|
+
actual_settings = nil
|
283
|
+
expect_any_instance_of(OneLogin::RubySaml::Logoutrequest).to receive(:create) do |_, settings|
|
284
|
+
actual_settings = settings
|
285
|
+
"http://localhost:8009/saml/logout"
|
231
286
|
end
|
232
|
-
}
|
233
287
|
|
234
|
-
|
235
|
-
@
|
236
|
-
|
288
|
+
delete :destroy
|
289
|
+
expect(actual_settings.name_identifier_value).to eq("user@example.com")
|
290
|
+
expect(actual_settings.sessionindex).to eq("sessionindex")
|
237
291
|
end
|
292
|
+
end
|
238
293
|
|
239
|
-
|
240
|
-
|
294
|
+
context "with a specified idp" do
|
295
|
+
before do
|
296
|
+
Devise.idp_settings_adapter = idp_providers_adapter
|
241
297
|
end
|
242
298
|
|
243
|
-
it "redirects to the associated IdP
|
244
|
-
|
299
|
+
it "redirects to the associated IdP SSO target url" do
|
300
|
+
expect(DeviseSamlAuthenticatable::DefaultIdpEntityIdReader).to receive(:entity_id)
|
301
|
+
delete :destroy
|
245
302
|
expect(controller).to have_received(:sign_out)
|
246
|
-
expect(idp_providers_adapter).to have_received(:settings).with("http://www.example.com")
|
247
303
|
expect(response).to redirect_to(%r(\Ahttp://idp_slo_url\?SAMLRequest=))
|
248
304
|
end
|
305
|
+
|
306
|
+
context "with a specified idp entity id reader" do
|
307
|
+
class OurIdpEntityIdReader
|
308
|
+
def self.entity_id(params)
|
309
|
+
params[:entity_id]
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
subject(:do_delete) {
|
314
|
+
if Rails::VERSION::MAJOR > 4
|
315
|
+
delete :destroy, params: {entity_id: "http://www.example.com"}
|
316
|
+
else
|
317
|
+
delete :destroy, entity_id: "http://www.example.com"
|
318
|
+
end
|
319
|
+
}
|
320
|
+
|
321
|
+
before do
|
322
|
+
@default_reader = Devise.idp_entity_id_reader
|
323
|
+
Devise.idp_entity_id_reader = OurIdpEntityIdReader # which will have some different behavior
|
324
|
+
end
|
325
|
+
|
326
|
+
after do
|
327
|
+
Devise.idp_entity_id_reader = @default_reader
|
328
|
+
end
|
329
|
+
|
330
|
+
it "redirects to the associated IdP SLO target url" do
|
331
|
+
do_delete
|
332
|
+
expect(controller).to have_received(:sign_out)
|
333
|
+
expect(idp_providers_adapter).to have_received(:settings).with("http://www.example.com")
|
334
|
+
expect(response).to redirect_to(%r(\Ahttp://idp_slo_url\?SAMLRequest=))
|
335
|
+
end
|
336
|
+
end
|
249
337
|
end
|
250
338
|
end
|
251
339
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'support/ruby_saml_support'
|
2
3
|
|
3
4
|
describe DeviseSamlAuthenticatable::SamlConfig do
|
5
|
+
include RubySamlSupport
|
6
|
+
|
4
7
|
let(:saml_config) { controller.saml_config }
|
5
8
|
let(:controller) { Class.new { include DeviseSamlAuthenticatable::SamlConfig }.new }
|
6
9
|
|
@@ -26,32 +29,54 @@ describe DeviseSamlAuthenticatable::SamlConfig do
|
|
26
29
|
let(:saml_config) { controller.saml_config(idp_entity_id) }
|
27
30
|
let(:idp_providers_adapter) {
|
28
31
|
Class.new {
|
32
|
+
extend RubySamlSupport
|
33
|
+
|
29
34
|
def self.settings(idp_entity_id)
|
30
35
|
#some hash of stuff (by doing a fetch, in our case, but could also be a giant hash keyed by idp_entity_id)
|
31
36
|
if idp_entity_id == "http://www.example.com"
|
32
|
-
{
|
37
|
+
base = {
|
33
38
|
assertion_consumer_service_url: "acs_url",
|
34
39
|
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
35
40
|
name_identifier_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
36
41
|
issuer: "sp_issuer",
|
37
42
|
idp_entity_id: "http://www.example.com",
|
38
43
|
authn_context: "",
|
39
|
-
idp_slo_target_url: "idp_slo_url",
|
40
|
-
idp_sso_target_url: "idp_sso_url",
|
41
44
|
idp_cert: "idp_cert"
|
42
45
|
}
|
46
|
+
with_ruby_saml_1_12_or_greater(proc {
|
47
|
+
base.merge!(
|
48
|
+
idp_slo_service_url: "idp_slo_url",
|
49
|
+
idp_sso_service_url: "idp_sso_url",
|
50
|
+
)
|
51
|
+
}, else_do: proc {
|
52
|
+
base.merge!(
|
53
|
+
idp_slo_target_url: "idp_slo_url",
|
54
|
+
idp_sso_target_url: "idp_sso_url",
|
55
|
+
)
|
56
|
+
})
|
57
|
+
base
|
43
58
|
elsif idp_entity_id == "http://www.example.com_other"
|
44
|
-
{
|
59
|
+
base = {
|
45
60
|
assertion_consumer_service_url: "acs_url_other",
|
46
61
|
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST_other",
|
47
62
|
name_identifier_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress_other",
|
48
63
|
issuer: "sp_issuer_other",
|
49
64
|
idp_entity_id: "http://www.example.com_other",
|
50
65
|
authn_context: "_other",
|
51
|
-
idp_slo_target_url: "idp_slo_url_other",
|
52
|
-
idp_sso_target_url: "idp_sso_url_other",
|
53
66
|
idp_cert: "idp_cert_other"
|
54
67
|
}
|
68
|
+
with_ruby_saml_1_12_or_greater(proc {
|
69
|
+
base.merge!(
|
70
|
+
idp_slo_service_url: "idp_slo_url_other",
|
71
|
+
idp_sso_service_url: "idp_sso_url_other",
|
72
|
+
)
|
73
|
+
}, else_do: proc {
|
74
|
+
base.merge!(
|
75
|
+
idp_slo_target_url: "idp_slo_url_other",
|
76
|
+
idp_sso_target_url: "idp_sso_url_other",
|
77
|
+
)
|
78
|
+
})
|
79
|
+
base
|
55
80
|
else
|
56
81
|
{}
|
57
82
|
end
|
@@ -63,7 +88,11 @@ describe DeviseSamlAuthenticatable::SamlConfig do
|
|
63
88
|
let(:idp_entity_id) { "http://www.example.com" }
|
64
89
|
it "uses the settings from the adapter for that idp" do
|
65
90
|
expect(saml_config.idp_entity_id).to eq (idp_entity_id)
|
66
|
-
|
91
|
+
with_ruby_saml_1_12_or_greater(proc {
|
92
|
+
expect(saml_config.idp_sso_service_url).to eq('idp_sso_url')
|
93
|
+
}, else_do: proc {
|
94
|
+
expect(saml_config.idp_sso_target_url).to eq('idp_sso_url')
|
95
|
+
})
|
67
96
|
expect(saml_config.class).to eq OneLogin::RubySaml::Settings
|
68
97
|
end
|
69
98
|
end
|
@@ -72,7 +101,11 @@ describe DeviseSamlAuthenticatable::SamlConfig do
|
|
72
101
|
let(:idp_entity_id) { "http://www.example.com_other" }
|
73
102
|
it "returns the other idp settings" do
|
74
103
|
expect(saml_config.idp_entity_id).to eq (idp_entity_id)
|
75
|
-
|
104
|
+
with_ruby_saml_1_12_or_greater(proc {
|
105
|
+
expect(saml_config.idp_sso_service_url).to eq('idp_sso_url_other')
|
106
|
+
}, else_do: proc {
|
107
|
+
expect(saml_config.idp_sso_target_url).to eq('idp_sso_url_other')
|
108
|
+
})
|
76
109
|
expect(saml_config.class).to eq OneLogin::RubySaml::Settings
|
77
110
|
end
|
78
111
|
end
|
@@ -80,11 +113,8 @@ describe DeviseSamlAuthenticatable::SamlConfig do
|
|
80
113
|
end
|
81
114
|
|
82
115
|
context "when config/idp.yml exists" do
|
83
|
-
|
84
|
-
|
85
|
-
allow(Rails).to receive(:root).and_return("/railsroot")
|
86
|
-
allow(File).to receive(:exists?).with("/railsroot/config/idp.yml").and_return(true)
|
87
|
-
allow(File).to receive(:read).with("/railsroot/config/idp.yml").and_return(<<-IDP)
|
116
|
+
let(:idp_yaml) {
|
117
|
+
yaml = <<-IDP
|
88
118
|
---
|
89
119
|
environment:
|
90
120
|
assertion_consumer_logout_service_binding: assertion_consumer_logout_service_binding
|
@@ -104,8 +134,6 @@ environment:
|
|
104
134
|
idp_cert_fingerprint: idp_cert_fingerprint
|
105
135
|
idp_cert_fingerprint_algorithm: idp_cert_fingerprint_algorithm
|
106
136
|
idp_entity_id: idp_entity_id
|
107
|
-
idp_slo_target_url: idp_slo_target_url
|
108
|
-
idp_sso_target_url: idp_sso_target_url
|
109
137
|
issuer: issuer
|
110
138
|
name_identifier_format: name_identifier_format
|
111
139
|
name_identifier_value: name_identifier_value
|
@@ -116,6 +144,20 @@ environment:
|
|
116
144
|
sessionindex: sessionindex
|
117
145
|
sp_name_qualifier: sp_name_qualifier
|
118
146
|
IDP
|
147
|
+
with_ruby_saml_1_12_or_greater(proc { yaml << <<SERVICE_URLS }, else_do: proc { yaml << <<TARGET_URLS })
|
148
|
+
idp_slo_service_url: idp_slo_service_url
|
149
|
+
idp_sso_service_url: idp_sso_service_url
|
150
|
+
SERVICE_URLS
|
151
|
+
idp_slo_target_url: idp_slo_service_url
|
152
|
+
idp_sso_target_url: idp_sso_service_url
|
153
|
+
TARGET_URLS
|
154
|
+
yaml
|
155
|
+
}
|
156
|
+
before do
|
157
|
+
allow(Rails).to receive(:env).and_return("environment")
|
158
|
+
allow(Rails).to receive(:root).and_return("/railsroot")
|
159
|
+
allow(File).to receive(:exists?).with("/railsroot/config/idp.yml").and_return(true)
|
160
|
+
allow(File).to receive(:read).with("/railsroot/config/idp.yml").and_return(idp_yaml)
|
119
161
|
end
|
120
162
|
|
121
163
|
it "uses that file's contents" do
|
@@ -136,8 +178,13 @@ environment:
|
|
136
178
|
expect(saml_config.idp_cert_fingerprint).to eq('idp_cert_fingerprint')
|
137
179
|
expect(saml_config.idp_cert_fingerprint_algorithm).to eq('idp_cert_fingerprint_algorithm')
|
138
180
|
expect(saml_config.idp_entity_id).to eq('idp_entity_id')
|
139
|
-
|
140
|
-
|
181
|
+
with_ruby_saml_1_12_or_greater(proc {
|
182
|
+
expect(saml_config.idp_slo_service_url).to eq('idp_slo_service_url')
|
183
|
+
expect(saml_config.idp_sso_service_url).to eq('idp_sso_service_url')
|
184
|
+
}, else_do: proc {
|
185
|
+
expect(saml_config.idp_slo_target_url).to eq('idp_slo_service_url')
|
186
|
+
expect(saml_config.idp_sso_target_url).to eq('idp_sso_service_url')
|
187
|
+
})
|
141
188
|
expect(saml_config.issuer).to eq('issuer')
|
142
189
|
expect(saml_config.name_identifier_format).to eq('name_identifier_format')
|
143
190
|
expect(saml_config.name_identifier_value).to eq('name_identifier_value')
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'rails_helper'
|
2
|
+
require 'support/ruby_saml_support'
|
2
3
|
|
3
4
|
describe Devise::Strategies::SamlAuthenticatable do
|
5
|
+
include RubySamlSupport
|
6
|
+
|
4
7
|
subject(:strategy) { described_class.new(env, :user) }
|
5
8
|
let(:env) { {} }
|
6
9
|
let(:errors) { ["Test1", "Test2"] }
|
@@ -16,7 +19,7 @@ describe Devise::Strategies::SamlAuthenticatable do
|
|
16
19
|
let(:user) { double(:user) }
|
17
20
|
before do
|
18
21
|
allow(strategy).to receive(:mapping).and_return(mapping)
|
19
|
-
allow(user).to
|
22
|
+
allow(user).to(receive(:after_saml_authentication)) if user
|
20
23
|
end
|
21
24
|
|
22
25
|
let(:params) { {} }
|
@@ -54,17 +57,27 @@ describe Devise::Strategies::SamlAuthenticatable do
|
|
54
57
|
let(:idp_providers_adapter) {
|
55
58
|
Class.new {
|
56
59
|
def self.settings(idp_entity_id)
|
57
|
-
{
|
60
|
+
base = {
|
58
61
|
assertion_consumer_service_url: "acs_url",
|
59
62
|
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
60
63
|
name_identifier_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
61
64
|
issuer: "sp_issuer",
|
62
65
|
idp_entity_id: "http://www.example.com",
|
63
66
|
authn_context: "",
|
64
|
-
idp_slo_target_url: "idp_slo_url",
|
65
|
-
idp_sso_target_url: "http://idp_sso_url",
|
66
67
|
idp_cert: "idp_cert"
|
67
68
|
}
|
69
|
+
with_ruby_saml_1_12_or_greater(proc {
|
70
|
+
base.merge!(
|
71
|
+
idp_slo_service_url: "idp_slo_url",
|
72
|
+
idp_sso_service_url: "http://idp_sso_url",
|
73
|
+
)
|
74
|
+
}, else_do: proc {
|
75
|
+
base.merge!(
|
76
|
+
idp_slo_target_url: "idp_slo_url",
|
77
|
+
idp_sso_target_url: "http://idp_sso_url",
|
78
|
+
)
|
79
|
+
})
|
80
|
+
base
|
68
81
|
end
|
69
82
|
}
|
70
83
|
}
|
@@ -93,8 +106,10 @@ describe Devise::Strategies::SamlAuthenticatable do
|
|
93
106
|
let(:user) { nil }
|
94
107
|
|
95
108
|
it "fails to authenticate" do
|
96
|
-
expect(strategy).to receive(:fail!).with(:invalid)
|
97
109
|
strategy.authenticate!
|
110
|
+
expect(strategy).to be_halted
|
111
|
+
expect(strategy.message).to be(:invalid)
|
112
|
+
expect(strategy.result).to be(:failure)
|
98
113
|
end
|
99
114
|
|
100
115
|
it 'logs the error' do
|
@@ -152,6 +167,40 @@ describe Devise::Strategies::SamlAuthenticatable do
|
|
152
167
|
strategy.authenticate!
|
153
168
|
end
|
154
169
|
end
|
170
|
+
|
171
|
+
context "when saml_validate_in_response_to is opted-in to" do
|
172
|
+
let(:transaction_id) { "abc123" }
|
173
|
+
|
174
|
+
before do
|
175
|
+
allow(Devise).to receive(:saml_validate_in_response_to).and_return(true)
|
176
|
+
allow_any_instance_of(ActionDispatch::Request).to receive(:session).and_return(session)
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when the session has a saml_transaction_id" do
|
180
|
+
let(:session) { { saml_transaction_id: transaction_id }}
|
181
|
+
|
182
|
+
it "is valid with the matches_request_id parameter" do
|
183
|
+
expect(OneLogin::RubySaml::Response).to receive(:new).with(params[:SAMLResponse], hash_including(matches_request_id: transaction_id))
|
184
|
+
expect(strategy).to be_valid
|
185
|
+
end
|
186
|
+
|
187
|
+
it "authenticates with the matches_request_id parameter" do
|
188
|
+
expect(OneLogin::RubySaml::Response).to receive(:new).with(params[:SAMLResponse], hash_including(matches_request_id: transaction_id))
|
189
|
+
|
190
|
+
expect(strategy).to receive(:success!).with(user)
|
191
|
+
strategy.authenticate!
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when the session is missing a saml_transaction_id" do
|
196
|
+
let(:session) { { } }
|
197
|
+
|
198
|
+
it "uses 'ID_MISSING' for matches_request_id so validation will fail" do
|
199
|
+
expect(OneLogin::RubySaml::Response).to receive(:new).with(params[:SAMLResponse], hash_including(matches_request_id: "ID_MISSING"))
|
200
|
+
strategy.authenticate!
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
155
204
|
end
|
156
205
|
|
157
206
|
it "is not valid without a SAMLResponse parameter" do
|
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in devise_saml_authenticatable.gemspec
|
4
|
+
gemspec path: '../..'
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem 'rake'
|
8
|
+
gem 'rspec', '~> 3.0'
|
9
|
+
gem 'rails', '~> 6.0.0'
|
10
|
+
gem 'rspec-rails', '~> 5.0'
|
11
|
+
gem 'sqlite3', '~> 1.4.0'
|
12
|
+
gem 'capybara'
|
13
|
+
gem 'poltergeist'
|
14
|
+
end
|
@@ -1,17 +1,27 @@
|
|
1
1
|
class IdpSettingsAdapter
|
2
2
|
def self.settings(idp_entity_id)
|
3
3
|
if idp_entity_id == "http://localhost:8020/saml/metadata"
|
4
|
-
{
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
base = {
|
5
|
+
assertion_consumer_service_url: "http://localhost:8020/users/saml/auth",
|
6
|
+
assertion_consumer_service_binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",
|
7
|
+
name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
8
|
+
issuer: "sp_issuer",
|
9
|
+
idp_entity_id: "http://localhost:8020/saml/metadata",
|
10
|
+
authn_context: "",
|
11
|
+
idp_cert_fingerprint: "9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D"
|
12
|
+
}
|
13
|
+
if Gem::Version.new(OneLogin::RubySaml::VERSION) >= Gem::Version.new("1.12.0")
|
14
|
+
base.merge!(
|
15
|
+
idp_slo_service_url: "http://localhost:8010/saml/logout",
|
16
|
+
idp_sso_service_url: "http://localhost:8010/saml/auth",
|
17
|
+
)
|
18
|
+
else
|
19
|
+
base.merge!(
|
11
20
|
idp_slo_target_url: "http://localhost:8010/saml/logout",
|
12
21
|
idp_sso_target_url: "http://localhost:8010/saml/auth",
|
13
|
-
|
14
|
-
|
22
|
+
)
|
23
|
+
end
|
24
|
+
base
|
15
25
|
else
|
16
26
|
{}
|
17
27
|
end
|
data/spec/support/rails_app.rb
CHANGED
@@ -21,12 +21,11 @@ def create_app(name, env = {})
|
|
21
21
|
puts "[#{name}] Creating Rails app"
|
22
22
|
rails_new_options = %w[-T -J -S --skip-spring --skip-listen --skip-bootsnap]
|
23
23
|
rails_new_options << "-O" if name == "idp"
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
24
|
+
env.merge!("RUBY_SAML_VERSION" => OneLogin::RubySaml::VERSION)
|
25
|
+
Dir.chdir(working_directory) do
|
26
|
+
FileUtils.rm_rf(name)
|
27
|
+
puts("[#{working_directory}] rails _#{Rails.version}_ new #{name} #{rails_new_options.join(" ")} -m #{File.expand_path("../#{name}_template.rb", __FILE__)}")
|
28
|
+
system(env, "rails", "_#{Rails.version}_", "new", name, *rails_new_options, "-m", File.expand_path("../#{name}_template.rb", __FILE__))
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
data/spec/support/sp_template.rb
CHANGED
@@ -8,13 +8,14 @@ use_subject_to_authenticate = ENV.fetch('USE_SUBJECT_TO_AUTHENTICATE')
|
|
8
8
|
idp_settings_adapter = ENV.fetch('IDP_SETTINGS_ADAPTER', "nil")
|
9
9
|
idp_entity_id_reader = ENV.fetch('IDP_ENTITY_ID_READER', '"DeviseSamlAuthenticatable::DefaultIdpEntityIdReader"')
|
10
10
|
saml_failed_callback = ENV.fetch('SAML_FAILED_CALLBACK', "nil")
|
11
|
+
ruby_saml_version = ENV.fetch("RUBY_SAML_VERSION")
|
11
12
|
|
12
13
|
if Rails::VERSION::MAJOR < 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR < 2)
|
13
14
|
gsub_file 'config/secrets.yml', /secret_key_base:.*$/, 'secret_key_base: "8b5889df1fcf03f76c7d66da02d8776bcc85b06bed7d9c592f076d9c8a5455ee6d4beae45986c3c030b40208db5e612f2a6ef8283036a352e3fae83c5eda36be"'
|
14
15
|
end
|
15
16
|
|
16
17
|
gem 'devise_saml_authenticatable', path: File.expand_path("../../..", __FILE__)
|
17
|
-
gem 'ruby-saml',
|
18
|
+
gem 'ruby-saml', ruby_saml_version
|
18
19
|
gem 'thin'
|
19
20
|
|
20
21
|
insert_into_file('Gemfile', after: /\z/) {
|
@@ -92,13 +93,24 @@ after_bundle do
|
|
92
93
|
config.saml_configure do |settings|
|
93
94
|
settings.assertion_consumer_service_url = "http://localhost:8020/users/saml/auth"
|
94
95
|
settings.issuer = "http://localhost:8020/saml/metadata"
|
95
|
-
settings.idp_slo_target_url = "http://localhost:8009/saml/logout"
|
96
|
-
settings.idp_sso_target_url = "http://localhost:8009/saml/auth"
|
97
96
|
settings.idp_cert_fingerprint = "9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D"
|
98
97
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
|
99
98
|
end
|
100
99
|
end
|
101
100
|
CONFIG
|
101
|
+
if Gem::Version.new(ruby_saml_version) >= Gem::Version.new("1.12.0")
|
102
|
+
gsub_file 'config/initializers/devise.rb', /^ config\.saml_configure do \|settings\|$/, <<CONFIG
|
103
|
+
config.saml_configure do |settings|
|
104
|
+
settings.idp_slo_service_url = "http://localhost:8009/saml/logout"
|
105
|
+
settings.idp_sso_service_url = "http://localhost:8009/saml/auth"
|
106
|
+
CONFIG
|
107
|
+
else
|
108
|
+
gsub_file 'config/initializers/devise.rb', /^ config\.saml_configure do \|settings\|$/, <<CONFIG
|
109
|
+
config.saml_configure do |settings|
|
110
|
+
settings.idp_slo_target_url = "http://localhost:8009/saml/logout"
|
111
|
+
settings.idp_sso_target_url = "http://localhost:8009/saml/auth"
|
112
|
+
CONFIG
|
113
|
+
end
|
102
114
|
|
103
115
|
generate :controller, 'home', 'index'
|
104
116
|
insert_into_file('app/controllers/home_controller.rb', after: "class HomeController < ApplicationController\n") {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_saml_authenticatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josef Sauter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: devise
|
@@ -45,9 +45,9 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- ".github/workflows/ci.yml"
|
48
49
|
- ".gitignore"
|
49
50
|
- ".rspec"
|
50
|
-
- ".travis.yml"
|
51
51
|
- Gemfile
|
52
52
|
- LICENSE
|
53
53
|
- README.md
|
@@ -82,12 +82,14 @@ files:
|
|
82
82
|
- spec/support/Gemfile.rails5
|
83
83
|
- spec/support/Gemfile.rails5.1
|
84
84
|
- spec/support/Gemfile.rails5.2
|
85
|
+
- spec/support/Gemfile.rails6
|
85
86
|
- spec/support/attribute-map.yml
|
86
87
|
- spec/support/attribute_map_resolver.rb.erb
|
87
88
|
- spec/support/idp_settings_adapter.rb.erb
|
88
89
|
- spec/support/idp_template.rb
|
89
90
|
- spec/support/rails_app.rb
|
90
91
|
- spec/support/response_encrypted_nameid.xml.base64
|
92
|
+
- spec/support/ruby_saml_support.rb
|
91
93
|
- spec/support/saml_idp-saml_slo_post.html.erb
|
92
94
|
- spec/support/saml_idp_controller.rb.erb
|
93
95
|
- spec/support/sp_template.rb
|
@@ -110,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
112
|
- !ruby/object:Gem::Version
|
111
113
|
version: '0'
|
112
114
|
requirements: []
|
113
|
-
rubygems_version: 3.
|
115
|
+
rubygems_version: 3.1.4
|
114
116
|
signing_key:
|
115
117
|
specification_version: 4
|
116
118
|
summary: SAML Authentication for devise
|
@@ -130,12 +132,14 @@ test_files:
|
|
130
132
|
- spec/support/Gemfile.rails5
|
131
133
|
- spec/support/Gemfile.rails5.1
|
132
134
|
- spec/support/Gemfile.rails5.2
|
135
|
+
- spec/support/Gemfile.rails6
|
133
136
|
- spec/support/attribute-map.yml
|
134
137
|
- spec/support/attribute_map_resolver.rb.erb
|
135
138
|
- spec/support/idp_settings_adapter.rb.erb
|
136
139
|
- spec/support/idp_template.rb
|
137
140
|
- spec/support/rails_app.rb
|
138
141
|
- spec/support/response_encrypted_nameid.xml.base64
|
142
|
+
- spec/support/ruby_saml_support.rb
|
139
143
|
- spec/support/saml_idp-saml_slo_post.html.erb
|
140
144
|
- spec/support/saml_idp_controller.rb.erb
|
141
145
|
- spec/support/sp_template.rb
|
data/.travis.yml
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- "2.0.0"
|
4
|
-
- "2.1.10"
|
5
|
-
- "2.2.10"
|
6
|
-
- "2.3.8"
|
7
|
-
- "2.4.10"
|
8
|
-
- "2.5.8"
|
9
|
-
- "2.6.6"
|
10
|
-
- "2.7.1"
|
11
|
-
gemfile:
|
12
|
-
- Gemfile
|
13
|
-
- spec/support/Gemfile.rails5.2
|
14
|
-
- spec/support/Gemfile.rails5.1
|
15
|
-
- spec/support/Gemfile.rails5
|
16
|
-
- spec/support/Gemfile.rails4
|
17
|
-
matrix:
|
18
|
-
allow_failures:
|
19
|
-
- rvm: "2.0.0"
|
20
|
-
gemfile: Gemfile
|
21
|
-
- rvm: "2.0.0"
|
22
|
-
gemfile: spec/support/Gemfile.rails5
|
23
|
-
- rvm: "2.0.0"
|
24
|
-
gemfile: spec/support/Gemfile.rails5.1
|
25
|
-
- rvm: "2.0.0"
|
26
|
-
gemfile: spec/support/Gemfile.rails5.2
|
27
|
-
- rvm: "2.1.10"
|
28
|
-
gemfile: Gemfile
|
29
|
-
- rvm: "2.1.10"
|
30
|
-
gemfile: spec/support/Gemfile.rails5
|
31
|
-
- rvm: "2.1.10"
|
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'
|
50
|
-
|
51
|
-
script:
|
52
|
-
- bundle exec rake
|