omniauth-saml 1.1.0 → 2.1.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.
Potentially problematic release.
This version of omniauth-saml might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +155 -8
- data/LICENSE.md +25 -0
- data/README.md +173 -38
- data/lib/omniauth/strategies/saml.rb +265 -32
- data/lib/omniauth-saml/version.rb +1 -1
- data/spec/omniauth/strategies/saml_spec.rb +358 -33
- data/spec/spec_helper.rb +11 -0
- metadata +87 -48
@@ -6,8 +6,8 @@ RSpec::Matchers.define :fail_with do |message|
|
|
6
6
|
end
|
7
7
|
end
|
8
8
|
|
9
|
-
def post_xml(xml
|
10
|
-
post "/auth/saml/callback", {'SAMLResponse' => load_xml(xml)}
|
9
|
+
def post_xml(xml = :example_response, opts = {})
|
10
|
+
post "/auth/saml/callback", opts.merge({'SAMLResponse' => load_xml(xml)})
|
11
11
|
end
|
12
12
|
|
13
13
|
describe OmniAuth::Strategies::SAML, :type => :strategy do
|
@@ -16,42 +16,103 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
16
16
|
let(:auth_hash){ last_request.env['omniauth.auth'] }
|
17
17
|
let(:saml_options) do
|
18
18
|
{
|
19
|
-
:assertion_consumer_service_url => "http://localhost:
|
20
|
-
:
|
21
|
-
:
|
19
|
+
:assertion_consumer_service_url => "http://localhost:9080/auth/saml/callback",
|
20
|
+
:single_logout_service_url => "http://localhost:9080/auth/saml/slo",
|
21
|
+
:idp_sso_service_url => "https://idp.sso.example.com/signon/29490",
|
22
|
+
:idp_slo_service_url => "https://idp.sso.example.com/signoff/29490",
|
22
23
|
:idp_cert_fingerprint => "C1:59:74:2B:E8:0C:6C:A9:41:0F:6E:83:F6:D1:52:25:45:58:89:FB",
|
23
|
-
:
|
24
|
-
:name_identifier_format => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
24
|
+
:idp_sso_service_url_runtime_params => {:original_param_key => :mapped_param_key},
|
25
|
+
:name_identifier_format => "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
26
|
+
:request_attributes => [
|
27
|
+
{ :name => 'email', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Email address' },
|
28
|
+
{ :name => 'name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Full name' },
|
29
|
+
{ :name => 'first_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Given name' },
|
30
|
+
{ :name => 'last_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Family name' }
|
31
|
+
],
|
32
|
+
:attribute_service_name => 'Required attributes'
|
25
33
|
}
|
26
34
|
end
|
27
35
|
let(:strategy) { [OmniAuth::Strategies::SAML, saml_options] }
|
28
36
|
|
29
|
-
describe '
|
37
|
+
describe 'POST /auth/saml' do
|
30
38
|
context 'without idp runtime params present' do
|
31
39
|
before do
|
32
|
-
|
40
|
+
post '/auth/saml'
|
33
41
|
end
|
34
42
|
|
35
43
|
it 'should get authentication page' do
|
36
|
-
last_response.
|
37
|
-
last_response.location.
|
38
|
-
last_response.location.
|
39
|
-
last_response.location.
|
40
|
-
last_response.location.
|
44
|
+
expect(last_response).to be_redirect
|
45
|
+
expect(last_response.location).to match /https:\/\/idp.sso.example.com\/signon\/29490/
|
46
|
+
expect(last_response.location).to match /\?SAMLRequest=/
|
47
|
+
expect(last_response.location).not_to match /mapped_param_key/
|
48
|
+
expect(last_response.location).not_to match /original_param_key/
|
41
49
|
end
|
42
50
|
end
|
43
51
|
|
44
52
|
context 'with idp runtime params' do
|
45
53
|
before do
|
46
|
-
|
54
|
+
post '/auth/saml', 'original_param_key' => 'original_param_value', 'mapped_param_key' => 'mapped_param_value'
|
47
55
|
end
|
48
56
|
|
49
57
|
it 'should get authentication page' do
|
50
|
-
last_response.
|
51
|
-
last_response.location.
|
52
|
-
last_response.location.
|
53
|
-
last_response.location.
|
54
|
-
last_response.location.
|
58
|
+
expect(last_response).to be_redirect
|
59
|
+
expect(last_response.location).to match /https:\/\/idp.sso.example.com\/signon\/29490/
|
60
|
+
expect(last_response.location).to match /\?SAMLRequest=/
|
61
|
+
expect(last_response.location).to match /\&mapped_param_key=original_param_value/
|
62
|
+
expect(last_response.location).not_to match /original_param_key/
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when the assertion_consumer_service_url is the default" do
|
67
|
+
before :each do
|
68
|
+
saml_options[:compress_request] = false
|
69
|
+
saml_options.delete(:assertion_consumer_service_url)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should send the current callback_url as the assertion_consumer_service_url' do
|
73
|
+
%w(foo.example.com bar.example.com).each do |host|
|
74
|
+
post "https://#{host}/auth/saml"
|
75
|
+
|
76
|
+
expect(last_response).to be_redirect
|
77
|
+
|
78
|
+
location = URI.parse(last_response.location)
|
79
|
+
query = Rack::Utils.parse_query location.query
|
80
|
+
expect(query).to have_key('SAMLRequest')
|
81
|
+
|
82
|
+
request = REXML::Document.new(Base64.decode64(query['SAMLRequest']))
|
83
|
+
expect(request.root).not_to be_nil
|
84
|
+
|
85
|
+
acs = request.root.attributes.get_attribute('AssertionConsumerServiceURL')
|
86
|
+
expect(acs.to_s).to eq "https://#{host}/auth/saml/callback"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'when authn request signing is requested' do
|
92
|
+
subject { post '/auth/saml' }
|
93
|
+
|
94
|
+
let(:private_key) { OpenSSL::PKey::RSA.new 2048 }
|
95
|
+
|
96
|
+
before do
|
97
|
+
saml_options[:compress_request] = false
|
98
|
+
|
99
|
+
saml_options[:private_key] = private_key.to_pem
|
100
|
+
saml_options[:security] = {
|
101
|
+
authn_requests_signed: true,
|
102
|
+
signature_method: XMLSecurity::Document::RSA_SHA256
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should sign the request' do
|
107
|
+
is_expected.to be_redirect
|
108
|
+
|
109
|
+
location = URI.parse(last_response.location)
|
110
|
+
query = Rack::Utils.parse_query location.query
|
111
|
+
expect(query).to have_key('SAMLRequest')
|
112
|
+
expect(query).to have_key('Signature')
|
113
|
+
expect(query).to have_key('SigAlg')
|
114
|
+
|
115
|
+
expect(query['SigAlg']).to eq XMLSecurity::Document::RSA_SHA256
|
55
116
|
end
|
56
117
|
end
|
57
118
|
end
|
@@ -62,7 +123,7 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
62
123
|
let(:xml) { :example_response }
|
63
124
|
|
64
125
|
before :each do
|
65
|
-
Time.
|
126
|
+
allow(Time).to receive(:now).and_return(Time.utc(2012, 11, 8, 20, 40, 00))
|
66
127
|
end
|
67
128
|
|
68
129
|
context "when the response is valid" do
|
@@ -71,33 +132,84 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
71
132
|
end
|
72
133
|
|
73
134
|
it "should set the uid to the nameID in the SAML response" do
|
74
|
-
auth_hash['uid'].
|
135
|
+
expect(auth_hash['uid']).to eq '_1f6fcf6be5e13b08b1e3610e7ff59f205fbd814f23'
|
75
136
|
end
|
76
137
|
|
77
138
|
it "should set the raw info to all attributes" do
|
78
|
-
auth_hash['extra']['raw_info'].to_hash.
|
79
|
-
'first_name' => 'Rajiv',
|
80
|
-
'last_name' => 'Manglani',
|
81
|
-
'email' => 'user@example.com',
|
82
|
-
'company_name' => 'Example Company'
|
83
|
-
|
139
|
+
expect(auth_hash['extra']['raw_info'].all.to_hash).to eq(
|
140
|
+
'first_name' => ['Rajiv'],
|
141
|
+
'last_name' => ['Manglani'],
|
142
|
+
'email' => ['user@example.com'],
|
143
|
+
'company_name' => ['Example Company'],
|
144
|
+
'fingerprint' => saml_options[:idp_cert_fingerprint]
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should set the response_object to the response object from ruby_saml response" do
|
149
|
+
expect(auth_hash['extra']['response_object']).to be_kind_of(OneLogin::RubySaml::Response)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "when fingerprint is empty and there's a fingerprint validator" do
|
154
|
+
before :each do
|
155
|
+
saml_options.delete(:idp_cert_fingerprint)
|
156
|
+
saml_options[:idp_cert_fingerprint_validator] = fingerprint_validator
|
157
|
+
end
|
158
|
+
|
159
|
+
let(:fingerprint_validator) { lambda { |_| "C1:59:74:2B:E8:0C:6C:A9:41:0F:6E:83:F6:D1:52:25:45:58:89:FB" } }
|
160
|
+
|
161
|
+
context "when the fingerprint validator returns a truthy value" do
|
162
|
+
before { post_xml }
|
163
|
+
|
164
|
+
it "should set the uid to the nameID in the SAML response" do
|
165
|
+
expect(auth_hash['uid']).to eq '_1f6fcf6be5e13b08b1e3610e7ff59f205fbd814f23'
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should set the raw info to all attributes" do
|
169
|
+
expect(auth_hash['extra']['raw_info'].all.to_hash).to eq(
|
170
|
+
'first_name' => ['Rajiv'],
|
171
|
+
'last_name' => ['Manglani'],
|
172
|
+
'email' => ['user@example.com'],
|
173
|
+
'company_name' => ['Example Company'],
|
174
|
+
'fingerprint' => 'C1:59:74:2B:E8:0C:6C:A9:41:0F:6E:83:F6:D1:52:25:45:58:89:FB'
|
175
|
+
)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when the fingerprint validator returns false" do
|
180
|
+
let(:fingerprint_validator) { lambda { |_| false } }
|
181
|
+
|
182
|
+
before { post_xml }
|
183
|
+
|
184
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
84
185
|
end
|
85
186
|
end
|
86
187
|
|
188
|
+
context "when the assertion_consumer_service_url is the default" do
|
189
|
+
before :each do
|
190
|
+
saml_options.delete(:assertion_consumer_service_url)
|
191
|
+
OmniAuth.config.full_host = 'http://localhost:9080'
|
192
|
+
post_xml
|
193
|
+
end
|
194
|
+
|
195
|
+
it { is_expected.not_to fail_with(:invalid_ticket) }
|
196
|
+
end
|
197
|
+
|
87
198
|
context "when there is no SAMLResponse parameter" do
|
88
199
|
before :each do
|
89
200
|
post '/auth/saml/callback'
|
90
201
|
end
|
91
202
|
|
92
|
-
it {
|
203
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
93
204
|
end
|
94
205
|
|
95
206
|
context "when there is no name id in the XML" do
|
96
207
|
before :each do
|
208
|
+
allow(Time).to receive(:now).and_return(Time.utc(2012, 11, 8, 23, 55, 00))
|
97
209
|
post_xml :no_name_id
|
98
210
|
end
|
99
211
|
|
100
|
-
it {
|
212
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
101
213
|
end
|
102
214
|
|
103
215
|
context "when the fingerprint is invalid" do
|
@@ -106,7 +218,7 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
106
218
|
post_xml
|
107
219
|
end
|
108
220
|
|
109
|
-
it {
|
221
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
110
222
|
end
|
111
223
|
|
112
224
|
context "when the digest is invalid" do
|
@@ -114,7 +226,7 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
114
226
|
post_xml :digest_mismatch
|
115
227
|
end
|
116
228
|
|
117
|
-
it {
|
229
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
118
230
|
end
|
119
231
|
|
120
232
|
context "when the signature is invalid" do
|
@@ -122,7 +234,220 @@ describe OmniAuth::Strategies::SAML, :type => :strategy do
|
|
122
234
|
post_xml :invalid_signature
|
123
235
|
end
|
124
236
|
|
125
|
-
it {
|
237
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
238
|
+
end
|
239
|
+
|
240
|
+
context "when the response is stale" do
|
241
|
+
before :each do
|
242
|
+
allow(Time).to receive(:now).and_return(Time.utc(2012, 11, 8, 20, 45, 00))
|
243
|
+
end
|
244
|
+
|
245
|
+
context "without :allowed_clock_drift option" do
|
246
|
+
before { post_xml :example_response }
|
247
|
+
|
248
|
+
it { is_expected.to fail_with(:invalid_ticket) }
|
249
|
+
end
|
250
|
+
|
251
|
+
context "with :allowed_clock_drift option" do
|
252
|
+
before :each do
|
253
|
+
saml_options[:allowed_clock_drift] = 60
|
254
|
+
post_xml :example_response
|
255
|
+
end
|
256
|
+
|
257
|
+
it { is_expected.to_not fail_with(:invalid_ticket) }
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context "when response has custom attributes" do
|
262
|
+
before :each do
|
263
|
+
saml_options[:idp_cert_fingerprint] = "3B:82:F1:F5:54:FC:A8:FF:12:B8:4B:B8:16:61:1D:E4:8E:9B:E2:3C"
|
264
|
+
saml_options[:attribute_statements] = {
|
265
|
+
email: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"],
|
266
|
+
first_name: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"],
|
267
|
+
last_name: ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname"]
|
268
|
+
}
|
269
|
+
post_xml :custom_attributes
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should obey attribute statements mapping" do
|
273
|
+
expect(auth_hash[:info]).to eq(
|
274
|
+
'first_name' => 'Rajiv',
|
275
|
+
'last_name' => 'Manglani',
|
276
|
+
'email' => 'user@example.com',
|
277
|
+
'name' => nil
|
278
|
+
)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "when using custom user id attribute" do
|
283
|
+
before :each do
|
284
|
+
saml_options[:idp_cert_fingerprint] = "3B:82:F1:F5:54:FC:A8:FF:12:B8:4B:B8:16:61:1D:E4:8E:9B:E2:3C"
|
285
|
+
saml_options[:uid_attribute] = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
|
286
|
+
post_xml :custom_attributes
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should return user id attribute" do
|
290
|
+
expect(auth_hash[:uid]).to eq("user@example.com")
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
context "when using custom user id attribute, but it is missing" do
|
295
|
+
before :each do
|
296
|
+
saml_options[:uid_attribute] = "missing_attribute"
|
297
|
+
post_xml
|
298
|
+
end
|
299
|
+
|
300
|
+
it "should fail to authenticate" do
|
301
|
+
should fail_with(:invalid_ticket)
|
302
|
+
expect(last_request.env['omniauth.error']).to be_instance_of(OmniAuth::Strategies::SAML::ValidationError)
|
303
|
+
expect(last_request.env['omniauth.error'].message).to eq("SAML response missing 'missing_attribute' attribute")
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context "when response is a logout response" do
|
308
|
+
before :each do
|
309
|
+
saml_options[:sp_entity_id] = "https://idp.sso.example.com/metadata/29490"
|
310
|
+
|
311
|
+
post "/auth/saml/slo", {
|
312
|
+
SAMLResponse: load_xml(:example_logout_response),
|
313
|
+
RelayState: "https://example.com/",
|
314
|
+
}, "rack.session" => {"saml_transaction_id" => "_3fef1069-d0c6-418a-b68d-6f008a4787e9"}
|
315
|
+
end
|
316
|
+
it "should redirect to relaystate" do
|
317
|
+
expect(last_response).to be_redirect
|
318
|
+
expect(last_response.location).to match /https:\/\/example.com\//
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
context "when request is a logout request" do
|
323
|
+
subject { post "/auth/saml/slo", params, "rack.session" => { "saml_uid" => "username@example.com" } }
|
324
|
+
|
325
|
+
before :each do
|
326
|
+
saml_options[:sp_entity_id] = "https://idp.sso.example.com/metadata/29490"
|
327
|
+
end
|
328
|
+
|
329
|
+
let(:params) do
|
330
|
+
{
|
331
|
+
"SAMLRequest" => load_xml(:example_logout_request),
|
332
|
+
"RelayState" => "https://example.com/",
|
333
|
+
}
|
334
|
+
end
|
335
|
+
|
336
|
+
context "when logout request is valid" do
|
337
|
+
before { subject }
|
338
|
+
|
339
|
+
it "should redirect to logout response" do
|
340
|
+
expect(last_response).to be_redirect
|
341
|
+
expect(last_response.location).to match /https:\/\/idp.sso.example.com\/signoff\/29490/
|
342
|
+
expect(last_response.location).to match /RelayState=https%3A%2F%2Fexample.com%2F/
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
context "when request is an invalid logout request" do
|
347
|
+
before :each do
|
348
|
+
allow_any_instance_of(OneLogin::RubySaml::SloLogoutrequest).to receive(:is_valid?).and_return(false)
|
349
|
+
end
|
350
|
+
|
351
|
+
# TODO: Maybe this should not raise an exception, but return some 4xx error instead?
|
352
|
+
it "should raise an exception" do
|
353
|
+
expect { subject }.
|
354
|
+
to raise_error(OmniAuth::Strategies::SAML::ValidationError, 'SAML failed to process LogoutRequest')
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
context "when request is a logout request but the request param is missing" do
|
359
|
+
let(:params) { {} }
|
360
|
+
|
361
|
+
# TODO: Maybe this should not raise an exception, but return a 422 error instead?
|
362
|
+
it 'should raise an exception' do
|
363
|
+
expect { subject }.
|
364
|
+
to raise_error(OmniAuth::Strategies::SAML::ValidationError, 'SAML logout response/request missing')
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
context "when sp initiated SLO" do
|
370
|
+
def test_default_relay_state(static_default_relay_state = nil, &block_default_relay_state)
|
371
|
+
saml_options["slo_default_relay_state"] = static_default_relay_state || block_default_relay_state
|
372
|
+
post "/auth/saml/spslo"
|
373
|
+
|
374
|
+
expect(last_response).to be_redirect
|
375
|
+
expect(last_response.location).to match /https:\/\/idp.sso.example.com\/signoff\/29490/
|
376
|
+
expect(last_response.location).to match /RelayState=https%3A%2F%2Fexample.com%2F/
|
377
|
+
end
|
378
|
+
|
379
|
+
it "should redirect to logout request" do
|
380
|
+
test_default_relay_state("https://example.com/")
|
381
|
+
end
|
382
|
+
|
383
|
+
it "should redirect to logout request with a block" do
|
384
|
+
test_default_relay_state do
|
385
|
+
"https://example.com/"
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
it "should redirect to logout request with a block with a request parameter" do
|
390
|
+
test_default_relay_state do |request|
|
391
|
+
"https://example.com/"
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
it "should give not implemented without an idp_slo_service_url" do
|
396
|
+
saml_options.delete(:idp_slo_service_url)
|
397
|
+
post "/auth/saml/spslo"
|
398
|
+
|
399
|
+
expect(last_response.status).to eq 501
|
400
|
+
expect(last_response.body).to match /Not Implemented/
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
describe 'POST /auth/saml/metadata' do
|
406
|
+
before do
|
407
|
+
saml_options[:sp_entity_id] = 'http://example.com/SAML'
|
408
|
+
post '/auth/saml/metadata'
|
409
|
+
end
|
410
|
+
|
411
|
+
it 'should get SP metadata page' do
|
412
|
+
expect(last_response.status).to eq 200
|
413
|
+
expect(last_response.header["Content-Type"]).to eq "application/xml"
|
414
|
+
end
|
415
|
+
|
416
|
+
it 'should configure attributes consuming service' do
|
417
|
+
expect(last_response.body).to match /AttributeConsumingService/
|
418
|
+
expect(last_response.body).to match /first_name/
|
419
|
+
expect(last_response.body).to match /last_name/
|
420
|
+
expect(last_response.body).to match /Required attributes/
|
421
|
+
expect(last_response.body).to match /entityID/
|
422
|
+
expect(last_response.body).to match /http:\/\/example.com\/SAML/
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
context 'when hitting an unknown route in our sub path' do
|
427
|
+
before { post '/auth/saml/unknown' }
|
428
|
+
|
429
|
+
specify { expect(last_response.status).to eql 404 }
|
430
|
+
end
|
431
|
+
|
432
|
+
context 'when hitting a completely unknown route' do
|
433
|
+
before { post '/unknown' }
|
434
|
+
|
435
|
+
specify { expect(last_response.status).to eql 404 }
|
436
|
+
end
|
437
|
+
|
438
|
+
context 'when hitting a route that contains a substring match for the strategy name' do
|
439
|
+
before { post '/auth/saml2/metadata' }
|
440
|
+
|
441
|
+
it 'should not set the strategy' do
|
442
|
+
expect(last_request.env['omniauth.strategy']).to be_nil
|
443
|
+
expect(last_response.status).to eql 404
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
describe 'subclass behavior' do
|
448
|
+
it 'registers subclasses in OmniAuth.strategies' do
|
449
|
+
subclass = Class.new(described_class)
|
450
|
+
expect(OmniAuth.strategies).to include(described_class, subclass)
|
126
451
|
end
|
127
452
|
end
|
128
453
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
require 'simplecov'
|
2
|
+
|
3
|
+
if ENV['TRAVIS']
|
4
|
+
require 'coveralls'
|
5
|
+
Coveralls.wear!
|
6
|
+
end
|
7
|
+
|
2
8
|
SimpleCov.start
|
3
9
|
|
4
10
|
require 'omniauth-saml'
|
@@ -7,6 +13,11 @@ require 'rexml/document'
|
|
7
13
|
require 'rexml/xpath'
|
8
14
|
require 'base64'
|
9
15
|
|
16
|
+
TEST_LOGGER = Logger.new(StringIO.new)
|
17
|
+
OneLogin::RubySaml::Logging.logger = TEST_LOGGER
|
18
|
+
OmniAuth.config.logger = TEST_LOGGER
|
19
|
+
OmniAuth.config.request_validation_phase = proc {}
|
20
|
+
|
10
21
|
RSpec.configure do |config|
|
11
22
|
config.include Rack::Test::Methods
|
12
23
|
end
|