saml_idp 0.7.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +1 -1
- data/README.md +71 -55
- data/lib/saml_idp/assertion_builder.rb +28 -3
- data/lib/saml_idp/configurator.rb +9 -3
- data/lib/saml_idp/controller.rb +27 -16
- data/lib/saml_idp/encryptor.rb +0 -1
- data/lib/saml_idp/fingerprint.rb +19 -0
- data/lib/saml_idp/incoming_metadata.rb +31 -1
- data/lib/saml_idp/metadata_builder.rb +25 -9
- data/lib/saml_idp/persisted_metadata.rb +4 -0
- data/lib/saml_idp/request.rb +103 -13
- data/lib/saml_idp/response_builder.rb +26 -6
- data/lib/saml_idp/saml_response.rb +62 -28
- data/lib/saml_idp/service_provider.rb +16 -6
- data/lib/saml_idp/signable.rb +1 -2
- data/lib/saml_idp/signature_builder.rb +2 -1
- data/lib/saml_idp/signed_info_builder.rb +2 -2
- data/lib/saml_idp/version.rb +1 -1
- data/lib/saml_idp/xml_security.rb +20 -15
- data/lib/saml_idp.rb +4 -3
- data/saml_idp.gemspec +46 -42
- 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 +151 -8
- data/spec/lib/saml_idp/attribute_decorator_spec.rb +8 -8
- data/spec/lib/saml_idp/configurator_spec.rb +45 -7
- data/spec/lib/saml_idp/controller_spec.rb +86 -25
- data/spec/lib/saml_idp/encryptor_spec.rb +4 -4
- data/spec/lib/saml_idp/fingerprint_spec.rb +14 -0
- data/spec/lib/saml_idp/incoming_metadata_spec.rb +134 -0
- data/spec/lib/saml_idp/metadata_builder_spec.rb +30 -17
- data/spec/lib/saml_idp/name_id_formatter_spec.rb +3 -3
- data/spec/lib/saml_idp/request_spec.rb +153 -64
- data/spec/lib/saml_idp/response_builder_spec.rb +5 -3
- data/spec/lib/saml_idp/saml_response_spec.rb +146 -12
- 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 +1 -1
- data/spec/rails_app/app/controllers/saml_idp_controller.rb +55 -3
- data/{app → spec/rails_app/app}/views/saml_idp/idp/new.html.erb +3 -4
- data/{app → spec/rails_app/app}/views/saml_idp/idp/saml_post.html.erb +1 -1
- data/spec/rails_app/config/application.rb +1 -6
- data/spec/rails_app/config/boot.rb +1 -1
- data/spec/rails_app/config/environments/development.rb +2 -5
- 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 +23 -1
- data/spec/support/certificates/sp_cert_req.csr +12 -0
- data/spec/support/certificates/sp_private_key.pem +16 -0
- data/spec/support/certificates/sp_x509_cert.crt +18 -0
- data/spec/support/saml_request_macros.rb +107 -5
- data/spec/support/security_helpers.rb +12 -2
- data/spec/xml_security_spec.rb +19 -15
- metadata +146 -80
- data/app/controllers/saml_idp/idp_controller.rb +0 -59
- data/spec/lib/saml_idp/.assertion_builder_spec.rb.swp +0 -0
|
@@ -24,6 +24,10 @@ module SamlIdp
|
|
|
24
24
|
key_transport: 'rsa-oaep-mgf1p',
|
|
25
25
|
}
|
|
26
26
|
end
|
|
27
|
+
let(:signed_response_opts) { true }
|
|
28
|
+
let(:unsigned_response_opts) { false }
|
|
29
|
+
let(:signed_assertion_opts) { true }
|
|
30
|
+
let(:compress_opts) { false }
|
|
27
31
|
let(:subject_encrypted) { described_class.new(reference_id,
|
|
28
32
|
response_id,
|
|
29
33
|
issuer_uri,
|
|
@@ -35,7 +39,12 @@ module SamlIdp
|
|
|
35
39
|
authn_context_classref,
|
|
36
40
|
expiry,
|
|
37
41
|
encryption_opts,
|
|
38
|
-
session_expiry
|
|
42
|
+
session_expiry,
|
|
43
|
+
nil,
|
|
44
|
+
nil,
|
|
45
|
+
unsigned_response_opts,
|
|
46
|
+
signed_assertion_opts,
|
|
47
|
+
compress_opts
|
|
39
48
|
)
|
|
40
49
|
}
|
|
41
50
|
|
|
@@ -50,7 +59,12 @@ module SamlIdp
|
|
|
50
59
|
authn_context_classref,
|
|
51
60
|
expiry,
|
|
52
61
|
nil,
|
|
53
|
-
session_expiry
|
|
62
|
+
session_expiry,
|
|
63
|
+
nil,
|
|
64
|
+
nil,
|
|
65
|
+
signed_response_opts,
|
|
66
|
+
signed_assertion_opts,
|
|
67
|
+
compress_opts
|
|
54
68
|
)
|
|
55
69
|
}
|
|
56
70
|
|
|
@@ -63,23 +77,143 @@ module SamlIdp
|
|
|
63
77
|
end
|
|
64
78
|
|
|
65
79
|
it "has a valid build" do
|
|
66
|
-
subject.build.
|
|
80
|
+
expect(subject.build).to be_present
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context "encrypted" do
|
|
84
|
+
it "builds encrypted" do
|
|
85
|
+
expect(subject_encrypted.build).to_not match(audience_uri)
|
|
86
|
+
encoded_xml = subject_encrypted.build
|
|
87
|
+
resp_settings = saml_settings(saml_acs_url)
|
|
88
|
+
resp_settings.private_key = Default::SECRET_KEY
|
|
89
|
+
resp_settings.issuer = audience_uri
|
|
90
|
+
saml_resp = OneLogin::RubySaml::Response.new(encoded_xml, settings: resp_settings)
|
|
91
|
+
saml_resp.soft = false
|
|
92
|
+
expect(saml_resp.is_valid?).to eq(true)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context "signed response" do
|
|
97
|
+
let(:resp_settings) do
|
|
98
|
+
resp_settings = saml_settings(saml_acs_url)
|
|
99
|
+
resp_settings.private_key = Default::SECRET_KEY
|
|
100
|
+
resp_settings.issuer = audience_uri
|
|
101
|
+
resp_settings
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "will build signed valid response" do
|
|
105
|
+
expect { subject.build }.not_to raise_error
|
|
106
|
+
signed_encoded_xml = subject.build
|
|
107
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
|
108
|
+
expect(
|
|
109
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
|
110
|
+
"//p:Response//ds:Signature",
|
|
111
|
+
{
|
|
112
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
113
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
|
114
|
+
}
|
|
115
|
+
)).to be_present
|
|
116
|
+
expect(saml_resp.send(:validate_signature)).to eq(true)
|
|
117
|
+
expect(saml_resp.is_valid?).to eq(true)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context "when signed_assertion_opts is true" do
|
|
121
|
+
it "builds a signed assertion" do
|
|
122
|
+
expect { subject.build }.not_to raise_error
|
|
123
|
+
signed_encoded_xml = subject.build
|
|
124
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
|
125
|
+
expect(
|
|
126
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
|
127
|
+
"//p:Response//a:Assertion//ds:Signature",
|
|
128
|
+
{
|
|
129
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
130
|
+
"a" => "urn:oasis:names:tc:SAML:2.0:assertion",
|
|
131
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
|
132
|
+
}
|
|
133
|
+
)).to be_present
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context "when signed_assertion_opts is false" do
|
|
138
|
+
let(:signed_assertion_opts) { false }
|
|
139
|
+
|
|
140
|
+
it "builds a raw assertion" do
|
|
141
|
+
expect { subject.build }.not_to raise_error
|
|
142
|
+
signed_encoded_xml = subject.build
|
|
143
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
|
144
|
+
expect(
|
|
145
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
|
146
|
+
"//p:Response//a:Assertion",
|
|
147
|
+
{
|
|
148
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
149
|
+
"a" => "urn:oasis:names:tc:SAML:2.0:assertion"
|
|
150
|
+
}
|
|
151
|
+
)).to be_present
|
|
152
|
+
|
|
153
|
+
expect(
|
|
154
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
|
155
|
+
"//p:Response//Assertion//ds:Signature",
|
|
156
|
+
{
|
|
157
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
158
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
|
159
|
+
}
|
|
160
|
+
)).to_not be_present
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context "when compress opts is true" do
|
|
165
|
+
let(:compress_opts) { true }
|
|
166
|
+
it "will build a compressed valid response" do
|
|
167
|
+
expect { subject.build }.not_to raise_error
|
|
168
|
+
compressed_signed_encoded_xml = subject.build
|
|
169
|
+
saml_resp = OneLogin::RubySaml::Response.new(compressed_signed_encoded_xml, settings: resp_settings)
|
|
170
|
+
expect(saml_resp.send(:validate_signature)).to eq(true)
|
|
171
|
+
expect(saml_resp.is_valid?).to eq(true)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
67
174
|
end
|
|
68
175
|
|
|
69
|
-
it "
|
|
70
|
-
|
|
71
|
-
|
|
176
|
+
it "will build signed valid response" do
|
|
177
|
+
expect { subject.build }.not_to raise_error
|
|
178
|
+
signed_encoded_xml = subject.build
|
|
72
179
|
resp_settings = saml_settings(saml_acs_url)
|
|
73
180
|
resp_settings.private_key = Default::SECRET_KEY
|
|
74
181
|
resp_settings.issuer = audience_uri
|
|
75
|
-
saml_resp = OneLogin::RubySaml::Response.new(
|
|
76
|
-
|
|
77
|
-
|
|
182
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
|
183
|
+
expect(
|
|
184
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
|
185
|
+
"//p:Response//ds:Signature",
|
|
186
|
+
{
|
|
187
|
+
"p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
188
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
|
189
|
+
}
|
|
190
|
+
)).to be_present
|
|
191
|
+
expect(saml_resp.send(:validate_signature)).to eq(true)
|
|
192
|
+
expect(saml_resp.is_valid?).to eq(true)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "will pass reference_id as SessionIndex" do
|
|
196
|
+
expect { subject.build }.not_to raise_error
|
|
197
|
+
signed_encoded_xml = subject.build
|
|
198
|
+
resp_settings = saml_settings(saml_acs_url)
|
|
199
|
+
resp_settings.private_key = Default::SECRET_KEY
|
|
200
|
+
resp_settings.issuer = audience_uri
|
|
201
|
+
saml_resp = OneLogin::RubySaml::Response.new(signed_encoded_xml, settings: resp_settings)
|
|
202
|
+
|
|
203
|
+
expect(
|
|
204
|
+
Nokogiri::XML(saml_resp.response).at_xpath(
|
|
205
|
+
"//saml:AuthnStatement/@SessionIndex",
|
|
206
|
+
{
|
|
207
|
+
"samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
|
208
|
+
"saml" => "urn:oasis:names:tc:SAML:2.0:assertion"
|
|
209
|
+
}
|
|
210
|
+
).value
|
|
211
|
+
).to eq("_#{reference_id}")
|
|
78
212
|
end
|
|
79
213
|
|
|
80
214
|
it "sets session expiration" do
|
|
81
215
|
saml_resp = OneLogin::RubySaml::Response.new(subject.build)
|
|
82
|
-
saml_resp.session_expires_at.
|
|
216
|
+
expect(saml_resp.session_expires_at).to eq Time.local(1990, "jan", 2).iso8601
|
|
83
217
|
end
|
|
84
218
|
|
|
85
219
|
context "session expiration is set to 0" do
|
|
@@ -89,14 +223,14 @@ module SamlIdp
|
|
|
89
223
|
resp_settings = saml_settings(saml_acs_url)
|
|
90
224
|
resp_settings.issuer = audience_uri
|
|
91
225
|
saml_resp = OneLogin::RubySaml::Response.new(subject.build, settings: resp_settings)
|
|
92
|
-
saml_resp.is_valid
|
|
226
|
+
expect(saml_resp.is_valid?).to eq(true)
|
|
93
227
|
end
|
|
94
228
|
|
|
95
229
|
it "doesn't set a session expiration" do
|
|
96
230
|
resp_settings = saml_settings(saml_acs_url)
|
|
97
231
|
resp_settings.issuer = audience_uri
|
|
98
232
|
saml_resp = OneLogin::RubySaml::Response.new(subject.build, settings: resp_settings)
|
|
99
|
-
saml_resp.session_expires_at.
|
|
233
|
+
expect(saml_resp.session_expires_at).to be_nil
|
|
100
234
|
end
|
|
101
235
|
end
|
|
102
236
|
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 }
|
|
@@ -9,11 +9,11 @@ module SamlIdp
|
|
|
9
9
|
) }
|
|
10
10
|
|
|
11
11
|
before do
|
|
12
|
-
Time.
|
|
12
|
+
allow(Time).to receive(:now).and_return Time.parse("Jul 31 2013")
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
it "builds a legit raw XML file" do
|
|
16
|
-
subject.raw.
|
|
16
|
+
expect(subject.raw).to eq("<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:SignedInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/><ds:SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#rsa-sha256\"/><ds:Reference URI=\"#_abc\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"/></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha256\"/><ds:DigestValue>em8csGAWynywpe8S4nN64o56/4DosXi2XWMY6RJ6YfA=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>jvEbD/rsiPKmoXy7Lhm+FGn88NPGlap4EcPZ2fvjBnk03YESs87FXAIiZZEzN5xq4sBZksUmZe2bV3rrr9sxQNgQawmrrvr66ot7cJiv0ETFArr6kQIZaR5g/V0M4ydxvrfefp6cQVI0hXvmxi830pq0tISiO4J7tyBNX/kvhZk=</ds:SignatureValue><KeyInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDqzCCAxSgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBhjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA05TVzEPMA0GA1UEBxMGU3lkbmV5MQwwCgYDVQQKDANQSVQxCTAHBgNVBAsMADEYMBYGA1UEAwwPbGF3cmVuY2VwaXQuY29tMSUwIwYJKoZIhvcNAQkBDBZsYXdyZW5jZS5waXRAZ21haWwuY29tMB4XDTEyMDQyODAyMjIyOFoXDTMyMDQyMzAyMjIyOFowgYYxCzAJBgNVBAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTEMMAoGA1UECgwDUElUMQkwBwYDVQQLDAAxGDAWBgNVBAMMD2xhd3JlbmNlcGl0LmNvbTElMCMGCSqGSIb3DQEJAQwWbGF3cmVuY2UucGl0QGdtYWlsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuBywPNlC1FopGLYfF96SotiK8Nj6/nW084O4omRMifzy7x955RLEy673q2aiJNB3LvE6Xvkt9cGtxtNoOXw1g2UvHKpldQbr6bOEjLNeDNW7j0ob+JrRvAUOK9CRgdyw5MC6lwqVQQ5C1DnaT/2fSBFjasBFTR24dEpfTy8HfKECAwEAAaOCASUwggEhMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgUgMB0GA1UdDgQWBBQNBGmmt3ytKpcJaBaYNbnyU2xkazATBgNVHSUEDDAKBggrBgEFBQcDATAdBglghkgBhvhCAQ0EEBYOVGVzdCBYNTA5IGNlcnQwgbMGA1UdIwSBqzCBqIAUDQRpprd8rSqXCWgWmDW58lNsZGuhgYykgYkwgYYxCzAJBgNVBAYTAkFVMQwwCgYDVQQIEwNOU1cxDzANBgNVBAcTBlN5ZG5leTEMMAoGA1UECgwDUElUMQkwBwYDVQQLDAAxGDAWBgNVBAMMD2xhd3JlbmNlcGl0LmNvbTElMCMGCSqGSIb3DQEJAQwWbGF3cmVuY2UucGl0QGdtYWlsLmNvbYIBATANBgkqhkiG9w0BAQsFAAOBgQAEcVUPBX7uZmzqZJfy+tUPOT5ImNQj8VE2lerhnFjnGPHmHIqhpzgnwHQujJfs/a309Wm5qwcCaC1eO5cWjcG0x3OjdllsgYDatl5GAumtBx8J3NhWRqNUgitCIkQlxHIwUfgQaCushYgDDL5YbIQa++egCgpIZ+T0Dj5oRew//A==</ds:X509Certificate></ds:X509Data></KeyInfo></ds:Signature>")
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -11,15 +11,15 @@ module SamlIdp
|
|
|
11
11
|
) }
|
|
12
12
|
|
|
13
13
|
before do
|
|
14
|
-
Time.
|
|
14
|
+
allow(Time).to receive(:now).and_return Time.parse("Jul 31 2013")
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
it "builds a legit raw XML file" do
|
|
18
|
-
subject.raw.
|
|
18
|
+
expect(subject.raw).to eq("<ds:SignedInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"></ds:SignatureMethod><ds:Reference URI=\"#_abc\"><ds:Transforms><ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"></ds:Transform><ds:Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"></ds:DigestMethod><ds:DigestValue>em8csGAWynywpe8S4nN64o56/4DosXi2XWMY6RJ6YfA=</ds:DigestValue></ds:Reference></ds:SignedInfo>")
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
it "builds a legit digest of the XML file" do
|
|
22
|
-
subject.signed.
|
|
22
|
+
expect(subject.signed).to eq("hKLeWLRgatHcV6N5Fc8aKveqNp6Y/J4m2WSYp0awGFtsCTa/2nab32wI3du+3kuuIy59EDKeUhHVxEfyhoHUo6xTZuO2N7XcTpSonuZ/CB3WjozC2Q/9elss3z1rOC3154v5pW4puirLPRoG+Pwi8SmptxNRHczr6NvmfYmmGfo=")
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
@@ -1,9 +1,61 @@
|
|
|
1
|
-
class SamlIdpController <
|
|
1
|
+
class SamlIdpController < ApplicationController
|
|
2
|
+
include SamlIdp::Controller
|
|
3
|
+
|
|
4
|
+
if Rails::VERSION::MAJOR >= 4
|
|
5
|
+
before_action :add_view_path, only: [:new, :create, :logout]
|
|
6
|
+
before_action :validate_saml_request, only: [:new, :create, :logout]
|
|
7
|
+
else
|
|
8
|
+
before_filter :add_view_path, only: [:new, :create, :logout]
|
|
9
|
+
before_filter :validate_saml_request, only: [:new, :create, :logout]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def new
|
|
13
|
+
render template: "saml_idp/idp/new"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def show
|
|
17
|
+
render xml: SamlIdp.metadata.signed
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create
|
|
21
|
+
unless params[:email].blank? && params[:password].blank?
|
|
22
|
+
person = idp_authenticate(params[:email], params[:password])
|
|
23
|
+
if person.nil?
|
|
24
|
+
@saml_idp_fail_msg = "Incorrect email or password."
|
|
25
|
+
else
|
|
26
|
+
@saml_response = idp_make_saml_response(person)
|
|
27
|
+
render :template => "saml_idp/idp/saml_post", :layout => false
|
|
28
|
+
return
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
render :template => "saml_idp/idp/new"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def logout
|
|
35
|
+
idp_logout
|
|
36
|
+
@saml_response = idp_make_saml_response(nil)
|
|
37
|
+
render :template => "saml_idp/idp/saml_post", :layout => false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def idp_logout
|
|
41
|
+
raise NotImplementedError
|
|
42
|
+
end
|
|
43
|
+
private :idp_logout
|
|
44
|
+
|
|
2
45
|
def idp_authenticate(email, password)
|
|
3
46
|
{ :email => email }
|
|
4
47
|
end
|
|
48
|
+
protected :idp_authenticate
|
|
5
49
|
|
|
6
|
-
def idp_make_saml_response(
|
|
7
|
-
encode_response(
|
|
50
|
+
def idp_make_saml_response(person)
|
|
51
|
+
encode_response(person[:email])
|
|
8
52
|
end
|
|
53
|
+
protected :idp_make_saml_response
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def add_view_path
|
|
58
|
+
prepend_view_path("app/views")
|
|
59
|
+
end
|
|
60
|
+
|
|
9
61
|
end
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
<% if @saml_idp_fail_msg %>
|
|
2
2
|
<div id="saml_idp_fail_msg" class="flash error"><%= @saml_idp_fail_msg %></div>
|
|
3
3
|
<% end %>
|
|
4
|
-
|
|
5
4
|
<%= form_tag do %>
|
|
6
5
|
<%= hidden_field_tag("SAMLRequest", params[:SAMLRequest]) %>
|
|
7
6
|
<%= hidden_field_tag("RelayState", params[:RelayState]) %>
|
|
7
|
+
<%= hidden_field_tag("SigAlg", params[:SigAlg]) %>
|
|
8
|
+
<%= hidden_field_tag("Signature", params[:Signature]) %>
|
|
8
9
|
|
|
9
10
|
<p>
|
|
10
11
|
<%= label_tag :email %>
|
|
11
12
|
<%= email_field_tag :email, params[:email], :autocapitalize => "off", :autocorrect => "off", :autofocus => "autofocus", :spellcheck => "false", :size => 30, :class => "email_pwd txt" %>
|
|
12
13
|
</p>
|
|
13
|
-
|
|
14
14
|
<p>
|
|
15
15
|
<%= label_tag :password %>
|
|
16
16
|
<%= password_field_tag :password, params[:password], :autocapitalize => "off", :autocorrect => "off", :spellcheck => "false", :size => 30, :class => "email_pwd txt" %>
|
|
17
17
|
</p>
|
|
18
|
-
|
|
19
18
|
<p>
|
|
20
19
|
<%= submit_tag "Sign in", :class => "button big blueish" %>
|
|
21
20
|
</p>
|
|
22
|
-
<% end %>
|
|
21
|
+
<% end %>
|
|
@@ -18,6 +18,7 @@ module RailsApp
|
|
|
18
18
|
|
|
19
19
|
# Custom directories with classes and modules you want to be autoloadable.
|
|
20
20
|
# config.autoload_paths += %W(#{config.root}/extras)
|
|
21
|
+
config.autoload_paths += %w[app/controllers]
|
|
21
22
|
|
|
22
23
|
# Only load the plugins named here, in the order given (default is alphabetical).
|
|
23
24
|
# :all can be used as a placeholder for all plugins not explicitly named.
|
|
@@ -50,11 +51,5 @@ module RailsApp
|
|
|
50
51
|
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
|
|
51
52
|
# parameters by using an attr_accessible or attr_protected declaration.
|
|
52
53
|
# config.active_record.whitelist_attributes = true
|
|
53
|
-
|
|
54
|
-
# Enable the asset pipeline
|
|
55
|
-
config.assets.enabled = true
|
|
56
|
-
|
|
57
|
-
# Version of your assets, change this if you want to expire all your assets
|
|
58
|
-
config.assets.version = '1.0'
|
|
59
54
|
end
|
|
60
55
|
end
|
|
@@ -4,6 +4,7 @@ RailsApp::Application.configure do
|
|
|
4
4
|
# In the development environment your application's code is reloaded on
|
|
5
5
|
# every request. This slows down response time but is perfect for development
|
|
6
6
|
# since you don't have to restart the web server when you make code changes.
|
|
7
|
+
config.eager_load = false if config.respond_to?(:eager_load)
|
|
7
8
|
config.cache_classes = false
|
|
8
9
|
|
|
9
10
|
# Log error messages when you accidentally call methods on nil.
|
|
@@ -29,9 +30,5 @@ RailsApp::Application.configure do
|
|
|
29
30
|
# with SQLite, MySQL, and PostgreSQL)
|
|
30
31
|
#config.active_record.auto_explain_threshold_in_seconds = 0.5
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
config.assets.compress = false
|
|
34
|
-
|
|
35
|
-
# Expands the lines which load the assets
|
|
36
|
-
config.assets.debug = true
|
|
33
|
+
config.hosts << "foo.example.com" if config.respond_to?(:hosts)
|
|
37
34
|
end
|
|
@@ -2,6 +2,7 @@ RailsApp::Application.configure do
|
|
|
2
2
|
# Settings specified here will take precedence over those in config/application.rb
|
|
3
3
|
|
|
4
4
|
# Code is not reloaded between requests
|
|
5
|
+
config.eager_load = true if config.respond_to?(:eager_load)
|
|
5
6
|
config.cache_classes = true
|
|
6
7
|
|
|
7
8
|
# Full error reports are disabled and caching is turned on
|
|
@@ -5,6 +5,7 @@ RailsApp::Application.configure do
|
|
|
5
5
|
# test suite. You never need to work with it otherwise. Remember that
|
|
6
6
|
# your test database is "scratch space" for the test suite and is wiped
|
|
7
7
|
# and recreated between test runs. Don't rely on the data there!
|
|
8
|
+
config.eager_load = true if config.respond_to?(:eager_load)
|
|
8
9
|
config.cache_classes = true
|
|
9
10
|
|
|
10
11
|
# Configure static asset server for tests with Cache-Control for performance
|
data/spec/spec_helper.rb
CHANGED
|
@@ -43,6 +43,28 @@ RSpec.configure do |config|
|
|
|
43
43
|
}
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
|
+
|
|
47
|
+
# To reset to default config
|
|
48
|
+
config.after do
|
|
49
|
+
SamlIdp.instance_variable_set(:@config, nil)
|
|
50
|
+
SamlIdp.configure do |c|
|
|
51
|
+
c.attributes = {
|
|
52
|
+
emailAddress: {
|
|
53
|
+
name: "email-address",
|
|
54
|
+
getter: ->(p) { "foo@example.com" }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
c.name_id.formats = {
|
|
59
|
+
"1.1" => {
|
|
60
|
+
email_address: ->(p) { "foo@example.com" }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
46
65
|
end
|
|
47
66
|
|
|
48
|
-
|
|
67
|
+
SamlIdp::Default::SERVICE_PROVIDER[:metadata_url] = 'https://example.com/meta'
|
|
68
|
+
SamlIdp::Default::SERVICE_PROVIDER[:response_hosts] = ['foo.example.com']
|
|
69
|
+
SamlIdp::Default::SERVICE_PROVIDER[:assertion_consumer_logout_service_url] = 'https://foo.example.com/saml/logout'
|
|
70
|
+
Capybara.default_host = "https://foo.example.com"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE REQUEST-----
|
|
2
|
+
MIIByTCCATICAQAwgYgxCzAJBgNVBAYTAmpwMQ4wDAYDVQQIDAVUb2t5bzELMAkG
|
|
3
|
+
A1UECgwCR1MxIDAeBgNVBAMMF2h0dHBzOi8vZm9vLmV4YW1wbGUuY29tMQwwCgYD
|
|
4
|
+
VQQHDANGb28xDDAKBgNVBAsMA0JvbzEeMBwGCSqGSIb3DQEJARYPZm9vQGV4YW1w
|
|
5
|
+
bGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8DVj2mVLQV7AjT+cn
|
|
6
|
+
Lv3kDnQFvAo3RdUeGGhplsYFacYByzNRD/jeguu1ahrvznDyZN8p3yB7OPbmt0r0
|
|
7
|
+
aGr+yYzPh6brgkf5u6FMtWTj94vLQuT/uyQGuzdBkiLb5mAWRMtm43oHXDK0v25J
|
|
8
|
+
tsG1PJnntkXfBDpFP1eWLO+jZwIDAQABoAAwDQYJKoZIhvcNAQENBQADgYEAd/J6
|
|
9
|
+
5zjrMhgjxuaMuWCiNN7IS4F9SKy+gEmhkpNVCpChbpggruaEIoERjDP/TkZn2dgL
|
|
10
|
+
VUeHTZB92t+wWfQbHNvEfbzqlV3XkuHkxewCwofnIV/k+8zG1Al5ELSKHehItxig
|
|
11
|
+
rnTuBrFYsd2j4HEVqLzm4NyCfL+xzn/D4U2ec50=
|
|
12
|
+
-----END CERTIFICATE REQUEST-----
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-----BEGIN PRIVATE KEY-----
|
|
2
|
+
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALwNWPaZUtBXsCNP
|
|
3
|
+
5ycu/eQOdAW8CjdF1R4YaGmWxgVpxgHLM1EP+N6C67VqGu/OcPJk3ynfIHs49ua3
|
|
4
|
+
SvRoav7JjM+HpuuCR/m7oUy1ZOP3i8tC5P+7JAa7N0GSItvmYBZEy2bjegdcMrS/
|
|
5
|
+
bkm2wbU8mee2Rd8EOkU/V5Ys76NnAgMBAAECgYEArwclVHCkebIECPnnxbqhKNCj
|
|
6
|
+
AGtifsuKbrZ9CDoDGSq31xeQLdTV6BSm2nVlmOnmilWEuG4qx0Xf2CGlrBI78kmv
|
|
7
|
+
vHCfFdaGnTxbmYnD0HN0u4RK2trsxWO+rEkJk14JE2eVD6ZRPrq1UOSMgGPrQSMb
|
|
8
|
+
SuwAHUu/j94eL8BXuhECQQD3jTlo3Y4VPWttP6XPNqKDP+jRYJs5G0Bch//S9Qy7
|
|
9
|
+
QzmU9/yAUk0BEOyqYcLxinjJhoq6bR2fiIibn+77z3jtAkEAwnhLwkGYOb7Nt3V6
|
|
10
|
+
dQLKx1BP9dnYH7qG/sCmAs7GHPv4LGluaz4zsh2pdEDF/Xar4gwTzUpxYo8FpkCH
|
|
11
|
+
rf4nIwJAVfWnGr/cR4nVVNFGHUcGdXbqvFHEdLb+yWK8NZ+79Qap5w2Zk2GAtb8P
|
|
12
|
+
vzZFQCRqPuhGIegj4jLB5PBLRwtLHQJBAJiWyWL4ExikRUhBTr/HXBL+Sm9u6i0j
|
|
13
|
+
L89unBQx6LNPZhB6/Z/6Y5fLvG2ycWgLGJ06usLnOYaLEHS9x3hXpp8CQQCdtQHw
|
|
14
|
+
xeLBPhRDpfWWbSmFr+bFxyD/4iQHTHToIs3kaecn6OJ4rczIFpGm2Bm7f4X7F3H3
|
|
15
|
+
DDy4jZ0R6iDqCcQD
|
|
16
|
+
-----END PRIVATE KEY-----
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIC2DCCAkGgAwIBAgIBADANBgkqhkiG9w0BAQ0FADCBiDELMAkGA1UEBhMCanAx
|
|
3
|
+
DjAMBgNVBAgMBVRva3lvMQswCQYDVQQKDAJHUzEgMB4GA1UEAwwXaHR0cHM6Ly9m
|
|
4
|
+
b28uZXhhbXBsZS5jb20xDDAKBgNVBAcMA0ZvbzEMMAoGA1UECwwDQm9vMR4wHAYJ
|
|
5
|
+
KoZIhvcNAQkBFg9mb29AZXhhbXBsZS5jb20wHhcNMjAwMTIzMDYyMzI5WhcNNDcw
|
|
6
|
+
NjA5MDYyMzI5WjCBiDELMAkGA1UEBhMCanAxDjAMBgNVBAgMBVRva3lvMQswCQYD
|
|
7
|
+
VQQKDAJHUzEgMB4GA1UEAwwXaHR0cHM6Ly9mb28uZXhhbXBsZS5jb20xDDAKBgNV
|
|
8
|
+
BAcMA0ZvbzEMMAoGA1UECwwDQm9vMR4wHAYJKoZIhvcNAQkBFg9mb29AZXhhbXBs
|
|
9
|
+
ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALwNWPaZUtBXsCNP5ycu
|
|
10
|
+
/eQOdAW8CjdF1R4YaGmWxgVpxgHLM1EP+N6C67VqGu/OcPJk3ynfIHs49ua3SvRo
|
|
11
|
+
av7JjM+HpuuCR/m7oUy1ZOP3i8tC5P+7JAa7N0GSItvmYBZEy2bjegdcMrS/bkm2
|
|
12
|
+
wbU8mee2Rd8EOkU/V5Ys76NnAgMBAAGjUDBOMB0GA1UdDgQWBBQMtOtrh2VS/mh4
|
|
13
|
+
awGbKA37vVnw+zAfBgNVHSMEGDAWgBQMtOtrh2VS/mh4awGbKA37vVnw+zAMBgNV
|
|
14
|
+
HRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBAHjTTm4Hyx1rfzygknc6q1dYwpEv
|
|
15
|
+
/3AsPiTnF4AfH/5kGIIXNzwg0ADsziFMJYRRR9eMu97CHQbr8gHt99P8uaen6cmJ
|
|
16
|
+
4VCwJLP2N8gZrycssimA3M83DWRRVZbxZhpuUWNajtYIxwyUbB7eRSJgz3Tc0opF
|
|
17
|
+
933YwucWuFzKSqn3
|
|
18
|
+
-----END CERTIFICATE-----
|