saml_idp 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +1 -1
- data/README.md +11 -5
- data/lib/saml_idp/configurator.rb +1 -0
- data/lib/saml_idp/controller.rb +6 -6
- data/lib/saml_idp/incoming_metadata.rb +4 -1
- data/lib/saml_idp/request.rb +13 -0
- data/lib/saml_idp/service_provider.rb +14 -0
- data/lib/saml_idp/version.rb +1 -1
- data/saml_idp.gemspec +25 -22
- data/spec/acceptance/idp_controller_spec.rb +5 -4
- data/spec/lib/saml_idp/algorithmable_spec.rb +6 -6
- data/spec/lib/saml_idp/assertion_builder_spec.rb +8 -8
- data/spec/lib/saml_idp/attribute_decorator_spec.rb +8 -8
- data/spec/lib/saml_idp/configurator_spec.rb +7 -7
- data/spec/lib/saml_idp/controller_spec.rb +23 -20
- data/spec/lib/saml_idp/encryptor_spec.rb +4 -4
- data/spec/lib/saml_idp/incoming_metadata_spec.rb +41 -0
- data/spec/lib/saml_idp/metadata_builder_spec.rb +7 -17
- data/spec/lib/saml_idp/name_id_formatter_spec.rb +3 -3
- data/spec/lib/saml_idp/request_spec.rb +22 -22
- data/spec/lib/saml_idp/response_builder_spec.rb +2 -2
- data/spec/lib/saml_idp/saml_response_spec.rb +6 -6
- data/spec/lib/saml_idp/service_provider_spec.rb +2 -2
- data/spec/lib/saml_idp/signable_spec.rb +1 -1
- data/spec/lib/saml_idp/signature_builder_spec.rb +2 -2
- data/spec/lib/saml_idp/signed_info_builder_spec.rb +3 -3
- data/spec/rails_app/app/controllers/saml_controller.rb +5 -1
- data/spec/rails_app/config/application.rb +0 -6
- data/spec/rails_app/config/environments/development.rb +1 -6
- data/spec/rails_app/config/environments/production.rb +1 -0
- data/spec/rails_app/config/environments/test.rb +1 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/saml_request_macros.rb +2 -1
- data/spec/xml_security_spec.rb +12 -12
- metadata +71 -39
- data/spec/lib/saml_idp/.assertion_builder_spec.rb.swp +0 -0
@@ -7,6 +7,9 @@ describe SamlIdp::Controller do
|
|
7
7
|
def render(*)
|
8
8
|
end
|
9
9
|
|
10
|
+
def head(*)
|
11
|
+
end
|
12
|
+
|
10
13
|
def params
|
11
14
|
@params ||= {}
|
12
15
|
end
|
@@ -14,8 +17,8 @@ describe SamlIdp::Controller do
|
|
14
17
|
it "should find the SAML ACS URL" do
|
15
18
|
requested_saml_acs_url = "https://example.com/saml/consume"
|
16
19
|
params[:SAMLRequest] = make_saml_request(requested_saml_acs_url)
|
17
|
-
validate_saml_request
|
18
|
-
saml_acs_url.
|
20
|
+
expect(validate_saml_request).to eq(true)
|
21
|
+
expect(saml_acs_url).to eq(requested_saml_acs_url)
|
19
22
|
end
|
20
23
|
|
21
24
|
context "SAML Responses" do
|
@@ -32,36 +35,36 @@ describe SamlIdp::Controller do
|
|
32
35
|
it "should create a SAML Response" do
|
33
36
|
saml_response = encode_response(principal, { audience_uri: 'http://example.com/issuer', issuer_uri: 'http://example.com', acs_url: 'https://foo.example.com/saml/consume' })
|
34
37
|
response = OneLogin::RubySaml::Response.new(saml_response)
|
35
|
-
response.name_id.
|
36
|
-
response.issuers.first.
|
38
|
+
expect(response.name_id).to eq("foo@example.com")
|
39
|
+
expect(response.issuers.first).to eq("http://example.com")
|
37
40
|
response.settings = saml_settings
|
38
|
-
response.is_valid
|
41
|
+
expect(response.is_valid?).to be_truthy
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
45
|
context "solicited Response" do
|
43
46
|
before(:each) do
|
44
47
|
params[:SAMLRequest] = make_saml_request
|
45
|
-
validate_saml_request
|
48
|
+
expect(validate_saml_request).to eq(true)
|
46
49
|
end
|
47
50
|
|
48
51
|
it "should create a SAML Response" do
|
49
52
|
saml_response = encode_response(principal)
|
50
53
|
response = OneLogin::RubySaml::Response.new(saml_response)
|
51
|
-
response.name_id.
|
52
|
-
response.issuers.first.
|
54
|
+
expect(response.name_id).to eq("foo@example.com")
|
55
|
+
expect(response.issuers.first).to eq("http://example.com")
|
53
56
|
response.settings = saml_settings
|
54
|
-
response.is_valid
|
57
|
+
expect(response.is_valid?).to be_truthy
|
55
58
|
end
|
56
59
|
|
57
60
|
it "should create a SAML Logout Response" do
|
58
61
|
params[:SAMLRequest] = make_saml_logout_request
|
59
|
-
validate_saml_request
|
62
|
+
expect(validate_saml_request).to eq(true)
|
60
63
|
expect(saml_request.logout_request?).to eq true
|
61
64
|
saml_response = encode_response(principal)
|
62
65
|
response = OneLogin::RubySaml::Logoutresponse.new(saml_response, saml_settings)
|
63
|
-
response.validate.
|
64
|
-
response.issuer.
|
66
|
+
expect(response.validate).to eq(true)
|
67
|
+
expect(response.issuer).to eq("http://example.com")
|
65
68
|
end
|
66
69
|
|
67
70
|
|
@@ -70,10 +73,10 @@ describe SamlIdp::Controller do
|
|
70
73
|
self.algorithm = algorithm_name
|
71
74
|
saml_response = encode_response(principal)
|
72
75
|
response = OneLogin::RubySaml::Response.new(saml_response)
|
73
|
-
response.name_id.
|
74
|
-
response.issuers.first.
|
76
|
+
expect(response.name_id).to eq("foo@example.com")
|
77
|
+
expect(response.issuers.first).to eq("http://example.com")
|
75
78
|
response.settings = saml_settings
|
76
|
-
response.is_valid
|
79
|
+
expect(response.is_valid?).to be_truthy
|
77
80
|
end
|
78
81
|
|
79
82
|
it "should encrypt SAML Response assertion" do
|
@@ -82,11 +85,11 @@ describe SamlIdp::Controller do
|
|
82
85
|
resp_settings = saml_settings
|
83
86
|
resp_settings.private_key = SamlIdp::Default::SECRET_KEY
|
84
87
|
response = OneLogin::RubySaml::Response.new(saml_response, settings: resp_settings)
|
85
|
-
response.document.to_s.
|
86
|
-
response.decrypted_document.to_s.
|
87
|
-
response.name_id.
|
88
|
-
response.issuers.first.
|
89
|
-
response.is_valid
|
88
|
+
expect(response.document.to_s).to_not match("foo@example.com")
|
89
|
+
expect(response.decrypted_document.to_s).to match("foo@example.com")
|
90
|
+
expect(response.name_id).to eq("foo@example.com")
|
91
|
+
expect(response.issuers.first).to eq("http://example.com")
|
92
|
+
expect(response.is_valid?).to be_truthy
|
90
93
|
end
|
91
94
|
end
|
92
95
|
end
|
@@ -5,11 +5,11 @@ require 'saml_idp/encryptor'
|
|
5
5
|
module SamlIdp
|
6
6
|
describe Encryptor do
|
7
7
|
let (:encryption_opts) do
|
8
|
-
{
|
8
|
+
{
|
9
9
|
cert: Default::X509_CERTIFICATE,
|
10
10
|
block_encryption: 'aes256-cbc',
|
11
11
|
key_transport: 'rsa-oaep-mgf1p',
|
12
|
-
}
|
12
|
+
}
|
13
13
|
end
|
14
14
|
|
15
15
|
subject { described_class.new encryption_opts }
|
@@ -17,11 +17,11 @@ module SamlIdp
|
|
17
17
|
it "encrypts XML" do
|
18
18
|
raw_xml = '<foo>bar</foo>'
|
19
19
|
encrypted_xml = subject.encrypt(raw_xml)
|
20
|
-
encrypted_xml.
|
20
|
+
expect(encrypted_xml).to_not match raw_xml
|
21
21
|
encrypted_doc = Nokogiri::XML::Document.parse(encrypted_xml)
|
22
22
|
encrypted_data = Xmlenc::EncryptedData.new(encrypted_doc.at_xpath('//xenc:EncryptedData', Xmlenc::NAMESPACES))
|
23
23
|
decrypted_xml = encrypted_data.decrypt(subject.encryption_key)
|
24
|
-
decrypted_xml.
|
24
|
+
expect(decrypted_xml).to eq(raw_xml)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module SamlIdp
|
3
|
+
|
4
|
+
metadata_1 = <<-eos
|
5
|
+
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="test" entityID="https://test-saml.com/saml">
|
6
|
+
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" AuthnRequestsSigned="true" WantAssertionsSigned="false">
|
7
|
+
</md:SPSSODescriptor>
|
8
|
+
</md:EntityDescriptor>
|
9
|
+
eos
|
10
|
+
|
11
|
+
metadata_2 = <<-eos
|
12
|
+
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="test" entityID="https://test-saml.com/saml">
|
13
|
+
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" AuthnRequestsSigned="true" WantAssertionsSigned="true">
|
14
|
+
</md:SPSSODescriptor>
|
15
|
+
</md:EntityDescriptor>
|
16
|
+
eos
|
17
|
+
|
18
|
+
metadata_3 = <<-eos
|
19
|
+
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="test" entityID="https://test-saml.com/saml">
|
20
|
+
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" AuthnRequestsSigned="true">
|
21
|
+
</md:SPSSODescriptor>
|
22
|
+
</md:EntityDescriptor>
|
23
|
+
eos
|
24
|
+
|
25
|
+
describe IncomingMetadata do
|
26
|
+
it 'should properly set sign_assertions to false' do
|
27
|
+
metadata = SamlIdp::IncomingMetadata.new(metadata_1)
|
28
|
+
expect(metadata.sign_assertions).to eq(false)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should properly set sign_assertions to true' do
|
32
|
+
metadata = SamlIdp::IncomingMetadata.new(metadata_2)
|
33
|
+
expect(metadata.sign_assertions).to eq(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should properly set sign_assertions to false when WantAssertionsSigned is not included' do
|
37
|
+
metadata = SamlIdp::IncomingMetadata.new(metadata_3)
|
38
|
+
expect(metadata.sign_assertions).to eq(false)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -2,18 +2,16 @@ require 'spec_helper'
|
|
2
2
|
module SamlIdp
|
3
3
|
describe MetadataBuilder do
|
4
4
|
it "has a valid fresh" do
|
5
|
-
subject.fresh.
|
5
|
+
expect(subject.fresh).to_not be_empty
|
6
6
|
end
|
7
7
|
|
8
8
|
it "signs valid xml" do
|
9
|
-
Saml::XML::Document.parse(subject.signed).valid_signature?(Default::FINGERPRINT).
|
9
|
+
expect(Saml::XML::Document.parse(subject.signed).valid_signature?(Default::FINGERPRINT)).to be_truthy
|
10
10
|
end
|
11
11
|
|
12
12
|
it "includes logout element" do
|
13
13
|
subject.configurator.single_logout_service_post_location = 'https://example.com/saml/logout'
|
14
|
-
subject.fresh.
|
15
|
-
'<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.com/saml/logout"/>'
|
16
|
-
)
|
14
|
+
expect(subject.fresh).to match('<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://example.com/saml/logout"/>')
|
17
15
|
end
|
18
16
|
|
19
17
|
context "technical contact" do
|
@@ -32,31 +30,23 @@ module SamlIdp
|
|
32
30
|
subject.configurator.technical_contact.telephone = "1-800-555-5555"
|
33
31
|
subject.configurator.technical_contact.email_address = "acme@example.com"
|
34
32
|
|
35
|
-
subject.fresh.
|
36
|
-
'<ContactPerson contactType="technical"><Company>ACME Corporation</Company><GivenName>Road</GivenName><SurName>Runner</SurName><EmailAddress>mailto:acme@example.com</EmailAddress><TelephoneNumber>1-800-555-5555</TelephoneNumber></ContactPerson>'
|
37
|
-
)
|
33
|
+
expect(subject.fresh).to match('<ContactPerson contactType="technical"><Company>ACME Corporation</Company><GivenName>Road</GivenName><SurName>Runner</SurName><EmailAddress>mailto:acme@example.com</EmailAddress><TelephoneNumber>1-800-555-5555</TelephoneNumber></ContactPerson>')
|
38
34
|
end
|
39
35
|
|
40
36
|
it "no fields" do
|
41
|
-
subject.fresh.
|
42
|
-
'<ContactPerson contactType="technical"></ContactPerson>'
|
43
|
-
)
|
37
|
+
expect(subject.fresh).to match('<ContactPerson contactType="technical"></ContactPerson>')
|
44
38
|
end
|
45
39
|
|
46
40
|
it "just email" do
|
47
41
|
subject.configurator.technical_contact.email_address = "acme@example.com"
|
48
|
-
subject.fresh.
|
49
|
-
'<ContactPerson contactType="technical"><EmailAddress>mailto:acme@example.com</EmailAddress></ContactPerson>'
|
50
|
-
)
|
42
|
+
expect(subject.fresh).to match('<ContactPerson contactType="technical"><EmailAddress>mailto:acme@example.com</EmailAddress></ContactPerson>')
|
51
43
|
end
|
52
44
|
|
53
45
|
end
|
54
46
|
|
55
47
|
it "includes logout element as HTTP Redirect" do
|
56
48
|
subject.configurator.single_logout_service_redirect_location = 'https://example.com/saml/logout'
|
57
|
-
subject.fresh.
|
58
|
-
'<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.com/saml/logout"/>'
|
59
|
-
)
|
49
|
+
expect(subject.fresh).to match('<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.com/saml/logout"/>')
|
60
50
|
end
|
61
51
|
end
|
62
52
|
end
|
@@ -7,7 +7,7 @@ module SamlIdp
|
|
7
7
|
let(:list) { { email_address: ->() { "foo@example.com" } } }
|
8
8
|
|
9
9
|
it "has a valid all" do
|
10
|
-
subject.all.
|
10
|
+
expect(subject.all).to eq ["urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress"]
|
11
11
|
end
|
12
12
|
|
13
13
|
end
|
@@ -21,7 +21,7 @@ module SamlIdp
|
|
21
21
|
}
|
22
22
|
|
23
23
|
it "has a valid all" do
|
24
|
-
subject.all.
|
24
|
+
expect(subject.all).to eq [
|
25
25
|
"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
|
26
26
|
"urn:oasis:names:tc:SAML:2.0:nameid-format:undefined",
|
27
27
|
]
|
@@ -32,7 +32,7 @@ module SamlIdp
|
|
32
32
|
let(:list) { [:email_address, :undefined] }
|
33
33
|
|
34
34
|
it "has a valid all" do
|
35
|
-
subject.all.
|
35
|
+
expect(subject.all).to eq [
|
36
36
|
"urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress",
|
37
37
|
"urn:oasis:names:tc:SAML:2.0:nameid-format:undefined",
|
38
38
|
]
|
@@ -9,12 +9,12 @@ module SamlIdp
|
|
9
9
|
subject { described_class.from_deflated_request deflated_request }
|
10
10
|
|
11
11
|
it "inflates" do
|
12
|
-
subject.request_id.
|
12
|
+
expect(subject.request_id).to eq("_af43d1a0-e111-0130-661a-3c0754403fdb")
|
13
13
|
end
|
14
14
|
|
15
15
|
it "handles invalid SAML" do
|
16
16
|
req = described_class.from_deflated_request "bang!"
|
17
|
-
req.valid
|
17
|
+
expect(req.valid?).to eq(false)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -22,51 +22,51 @@ module SamlIdp
|
|
22
22
|
subject { described_class.new raw_authn_request }
|
23
23
|
|
24
24
|
it "has a valid request_id" do
|
25
|
-
subject.request_id.
|
25
|
+
expect(subject.request_id).to eq("_af43d1a0-e111-0130-661a-3c0754403fdb")
|
26
26
|
end
|
27
27
|
|
28
28
|
it "has a valid acs_url" do
|
29
|
-
subject.acs_url.
|
29
|
+
expect(subject.acs_url).to eq("http://localhost:3000/saml/consume")
|
30
30
|
end
|
31
31
|
|
32
32
|
it "has a valid service_provider" do
|
33
|
-
subject.service_provider.
|
33
|
+
expect(subject.service_provider).to be_a ServiceProvider
|
34
34
|
end
|
35
35
|
|
36
36
|
it "has a valid service_provider" do
|
37
|
-
subject.service_provider.
|
37
|
+
expect(subject.service_provider).to be_truthy
|
38
38
|
end
|
39
39
|
|
40
40
|
it "has a valid issuer" do
|
41
|
-
subject.issuer.
|
41
|
+
expect(subject.issuer).to eq("localhost:3000")
|
42
42
|
end
|
43
43
|
|
44
44
|
it "has a valid valid_signature" do
|
45
|
-
subject.valid_signature
|
45
|
+
expect(subject.valid_signature?).to be_truthy
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should return acs_url for response_url" do
|
49
|
-
subject.response_url.
|
49
|
+
expect(subject.response_url).to eq(subject.acs_url)
|
50
50
|
end
|
51
51
|
|
52
52
|
it "is a authn request" do
|
53
|
-
subject.authn_request
|
53
|
+
expect(subject.authn_request?).to eq(true)
|
54
54
|
end
|
55
55
|
|
56
56
|
it "fetches internal request" do
|
57
|
-
subject.request['ID'].
|
57
|
+
expect(subject.request['ID']).to eq(subject.request_id)
|
58
58
|
end
|
59
59
|
|
60
60
|
it "has a valid authn context" do
|
61
|
-
subject.requested_authn_context.
|
61
|
+
expect(subject.requested_authn_context).to eq("urn:oasis:names:tc:SAML:2.0:ac:classes:Password")
|
62
62
|
end
|
63
63
|
|
64
64
|
it "does not permit empty issuer" do
|
65
65
|
raw_req = raw_authn_request.gsub('localhost:3000', '')
|
66
66
|
authn_request = described_class.new raw_req
|
67
|
-
authn_request.issuer.
|
68
|
-
authn_request.issuer.
|
69
|
-
authn_request.valid
|
67
|
+
expect(authn_request.issuer).to_not eq('')
|
68
|
+
expect(authn_request.issuer).to be_nil
|
69
|
+
expect(authn_request.valid?).to eq(false)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
@@ -76,31 +76,31 @@ module SamlIdp
|
|
76
76
|
subject { described_class.new raw_logout_request }
|
77
77
|
|
78
78
|
it "has a valid request_id" do
|
79
|
-
subject.request_id.
|
79
|
+
expect(subject.request_id).to eq('_some_response_id')
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should be flagged as a logout_request" do
|
83
|
-
subject.logout_request
|
83
|
+
expect(subject.logout_request?).to eq(true)
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should have a valid name_id" do
|
87
|
-
subject.name_id.
|
87
|
+
expect(subject.name_id).to eq('some_name_id')
|
88
88
|
end
|
89
89
|
|
90
90
|
it "should have a session index" do
|
91
|
-
subject.session_index.
|
91
|
+
expect(subject.session_index).to eq('abc123index')
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should have a valid issuer" do
|
95
|
-
subject.issuer.
|
95
|
+
expect(subject.issuer).to eq('http://example.com')
|
96
96
|
end
|
97
97
|
|
98
98
|
it "fetches internal request" do
|
99
|
-
subject.request['ID'].
|
99
|
+
expect(subject.request['ID']).to eq(subject.request_id)
|
100
100
|
end
|
101
101
|
|
102
102
|
it "should return logout_url for response_url" do
|
103
|
-
subject.response_url.
|
103
|
+
expect(subject.response_url).to eq(subject.logout_url)
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
@@ -25,7 +25,7 @@ module SamlIdp
|
|
25
25
|
|
26
26
|
it "builds a legit raw XML file" do
|
27
27
|
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
|
28
|
-
subject.raw.
|
28
|
+
expect(subject.raw).to eq("<samlp:Response ID=\"_abc\" Version=\"2.0\" IssueInstant=\"2010-06-01T13:00:00Z\" Destination=\"http://sportngin.com\" Consent=\"urn:oasis:names:tc:SAML:2.0:consent:unspecified\" InResponseTo=\"134\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"><Issuer xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://example.com</Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><Assertion xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"_abc\" IssueInstant=\"2013-07-31T05:00:00Z\" Version=\"2.0\"><Issuer>http://sportngin.com</Issuer><signature>stuff</signature><Subject><NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">jon.phenow@sportngin.com</NameID><SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><SubjectConfirmationData InResponseTo=\"123\" NotOnOrAfter=\"2013-07-31T05:03:00Z\" Recipient=\"http://saml.acs.url\"/></SubjectConfirmation></Subject><Conditions NotBefore=\"2013-07-31T04:59:55Z\" NotOnOrAfter=\"2013-07-31T06:00:00Z\"><AudienceRestriction><Audience>http://example.com</Audience></AudienceRestriction></Conditions><AttributeStatement><Attribute Name=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\"><AttributeValue>jon.phenow@sportngin.com</AttributeValue></Attribute></AttributeStatement><AuthnStatment AuthnInstant=\"2013-07-31T05:00:00Z\" SessionIndex=\"_abc\"><AuthnContext><AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef></AuthnContext></AuthnStatment></Assertion></samlp:Response>")
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -34,7 +34,7 @@ module SamlIdp
|
|
34
34
|
|
35
35
|
it "builds a legit raw XML file without a request ID" do
|
36
36
|
Timecop.travel(Time.zone.local(2010, 6, 1, 13, 0, 0)) do
|
37
|
-
subject.raw.
|
37
|
+
expect(subject.raw).to eq("<samlp:Response ID=\"_abc\" Version=\"2.0\" IssueInstant=\"2010-06-01T13:00:00Z\" Destination=\"http://sportngin.com\" Consent=\"urn:oasis:names:tc:SAML:2.0:consent:unspecified\" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"><Issuer xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\">http://example.com</Issuer><samlp:Status><samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\"/></samlp:Status><Assertion xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\" ID=\"_abc\" IssueInstant=\"2013-07-31T05:00:00Z\" Version=\"2.0\"><Issuer>http://sportngin.com</Issuer><signature>stuff</signature><Subject><NameID Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress\">jon.phenow@sportngin.com</NameID><SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"><SubjectConfirmationData InResponseTo=\"123\" NotOnOrAfter=\"2013-07-31T05:03:00Z\" Recipient=\"http://saml.acs.url\"/></SubjectConfirmation></Subject><Conditions NotBefore=\"2013-07-31T04:59:55Z\" NotOnOrAfter=\"2013-07-31T06:00:00Z\"><AudienceRestriction><Audience>http://example.com</Audience></AudienceRestriction></Conditions><AttributeStatement><Attribute Name=\"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress\"><AttributeValue>jon.phenow@sportngin.com</AttributeValue></Attribute></AttributeStatement><AuthnStatment AuthnInstant=\"2013-07-31T05:00:00Z\" SessionIndex=\"_abc\"><AuthnContext><AuthnContextClassRef>urn:federation:authentication:windows</AuthnContextClassRef></AuthnContext></AuthnStatment></Assertion></samlp:Response>")
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -63,23 +63,23 @@ module SamlIdp
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it "has a valid build" do
|
66
|
-
subject.build.
|
66
|
+
expect(subject.build).to be_present
|
67
67
|
end
|
68
68
|
|
69
69
|
it "builds encrypted" do
|
70
|
-
subject_encrypted.build.
|
70
|
+
expect(subject_encrypted.build).to_not match(audience_uri)
|
71
71
|
encoded_xml = subject_encrypted.build
|
72
72
|
resp_settings = saml_settings(saml_acs_url)
|
73
73
|
resp_settings.private_key = Default::SECRET_KEY
|
74
74
|
resp_settings.issuer = audience_uri
|
75
75
|
saml_resp = OneLogin::RubySaml::Response.new(encoded_xml, settings: resp_settings)
|
76
76
|
saml_resp.soft = false
|
77
|
-
saml_resp.is_valid
|
77
|
+
expect(saml_resp.is_valid?).to eq(true)
|
78
78
|
end
|
79
79
|
|
80
80
|
it "sets session expiration" do
|
81
81
|
saml_resp = OneLogin::RubySaml::Response.new(subject.build)
|
82
|
-
saml_resp.session_expires_at.
|
82
|
+
expect(saml_resp.session_expires_at).to eq Time.local(1990, "jan", 2).iso8601
|
83
83
|
end
|
84
84
|
|
85
85
|
context "session expiration is set to 0" do
|
@@ -89,14 +89,14 @@ module SamlIdp
|
|
89
89
|
resp_settings = saml_settings(saml_acs_url)
|
90
90
|
resp_settings.issuer = audience_uri
|
91
91
|
saml_resp = OneLogin::RubySaml::Response.new(subject.build, settings: resp_settings)
|
92
|
-
saml_resp.is_valid
|
92
|
+
expect(saml_resp.is_valid?).to eq(true)
|
93
93
|
end
|
94
94
|
|
95
95
|
it "doesn't set a session expiration" do
|
96
96
|
resp_settings = saml_settings(saml_acs_url)
|
97
97
|
resp_settings.issuer = audience_uri
|
98
98
|
saml_resp = OneLogin::RubySaml::Response.new(subject.build, settings: resp_settings)
|
99
|
-
saml_resp.session_expires_at.
|
99
|
+
expect(saml_resp.session_expires_at).to be_nil
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
@@ -14,11 +14,11 @@ module SamlIdp
|
|
14
14
|
let(:metadata_url) { "http://localhost:3000/metadata" }
|
15
15
|
|
16
16
|
it "has a valid fingerprint" do
|
17
|
-
subject.fingerprint.
|
17
|
+
expect(subject.fingerprint).to eq(fingerprint)
|
18
18
|
end
|
19
19
|
|
20
20
|
it "has a valid metadata_url" do
|
21
|
-
subject.metadata_url.
|
21
|
+
expect(subject.metadata_url).to eq(metadata_url)
|
22
22
|
end
|
23
23
|
|
24
24
|
it { should be_valid }
|