saml_idp 0.7.2 → 0.8.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 +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 }
|