cie-es 0.0.1

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +19 -0
  5. data/README.md +126 -0
  6. data/Rakefile +41 -0
  7. data/cie-es.gemspec +22 -0
  8. data/lib/cie/ruby-saml/authrequest.rb +205 -0
  9. data/lib/cie/ruby-saml/coding.rb +34 -0
  10. data/lib/cie/ruby-saml/error_handling.rb +27 -0
  11. data/lib/cie/ruby-saml/logging.rb +26 -0
  12. data/lib/cie/ruby-saml/logout_request.rb +126 -0
  13. data/lib/cie/ruby-saml/logout_response.rb +132 -0
  14. data/lib/cie/ruby-saml/metadata.rb +489 -0
  15. data/lib/cie/ruby-saml/request.rb +81 -0
  16. data/lib/cie/ruby-saml/response.rb +678 -0
  17. data/lib/cie/ruby-saml/settings.rb +89 -0
  18. data/lib/cie/ruby-saml/utils.rb +225 -0
  19. data/lib/cie/ruby-saml/validation_error.rb +7 -0
  20. data/lib/cie/ruby-saml/version.rb +5 -0
  21. data/lib/cie/xml_security.rb +166 -0
  22. data/lib/cie/xml_security_new.rb +373 -0
  23. data/lib/cie-es.rb +14 -0
  24. data/lib/schemas/saml20assertion_schema.xsd +283 -0
  25. data/lib/schemas/saml20protocol_schema.xsd +302 -0
  26. data/lib/schemas/xenc_schema.xsd +146 -0
  27. data/lib/schemas/xmldsig_schema.xsd +318 -0
  28. data/test/certificates/certificate1 +12 -0
  29. data/test/logoutrequest_test.rb +98 -0
  30. data/test/request_test.rb +53 -0
  31. data/test/response_test.rb +219 -0
  32. data/test/responses/adfs_response_sha1.xml +46 -0
  33. data/test/responses/adfs_response_sha256.xml +46 -0
  34. data/test/responses/adfs_response_sha384.xml +46 -0
  35. data/test/responses/adfs_response_sha512.xml +46 -0
  36. data/test/responses/no_signature_ns.xml +48 -0
  37. data/test/responses/open_saml_response.xml +56 -0
  38. data/test/responses/response1.xml.base64 +1 -0
  39. data/test/responses/response2.xml.base64 +79 -0
  40. data/test/responses/response3.xml.base64 +66 -0
  41. data/test/responses/response4.xml.base64 +93 -0
  42. data/test/responses/response5.xml.base64 +102 -0
  43. data/test/responses/response_with_ampersands.xml +139 -0
  44. data/test/responses/response_with_ampersands.xml.base64 +93 -0
  45. data/test/responses/simple_saml_php.xml +71 -0
  46. data/test/responses/wrapped_response_2.xml.base64 +150 -0
  47. data/test/settings_test.rb +43 -0
  48. data/test/test_helper.rb +65 -0
  49. data/test/xml_security_test.rb +123 -0
  50. metadata +119 -0
@@ -0,0 +1,318 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE schema
3
+ PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
4
+ [
5
+ <!ATTLIST schema
6
+ xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
7
+ <!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
8
+ <!ENTITY % p ''>
9
+ <!ENTITY % s ''>
10
+ ]>
11
+
12
+ <!-- Schema for XML Signatures
13
+ http://www.w3.org/2000/09/xmldsig#
14
+ $Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
15
+
16
+ Copyright 2001 The Internet Society and W3C (Massachusetts Institute
17
+ of Technology, Institut National de Recherche en Informatique et en
18
+ Automatique, Keio University). All Rights Reserved.
19
+ http://www.w3.org/Consortium/Legal/
20
+
21
+ This document is governed by the W3C Software License [1] as described
22
+ in the FAQ [2].
23
+
24
+ [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
25
+ [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
26
+ -->
27
+
28
+
29
+ <schema xmlns="http://www.w3.org/2001/XMLSchema"
30
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
31
+ targetNamespace="http://www.w3.org/2000/09/xmldsig#"
32
+ version="0.1" elementFormDefault="qualified">
33
+
34
+ <!-- Basic Types Defined for Signatures -->
35
+
36
+ <simpleType name="CryptoBinary">
37
+ <restriction base="base64Binary">
38
+ </restriction>
39
+ </simpleType>
40
+
41
+ <!-- Start Signature -->
42
+
43
+ <element name="Signature" type="ds:SignatureType"/>
44
+ <complexType name="SignatureType">
45
+ <sequence>
46
+ <element ref="ds:SignedInfo"/>
47
+ <element ref="ds:SignatureValue"/>
48
+ <element ref="ds:KeyInfo" minOccurs="0"/>
49
+ <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
50
+ </sequence>
51
+ <attribute name="Id" type="ID" use="optional"/>
52
+ </complexType>
53
+
54
+ <element name="SignatureValue" type="ds:SignatureValueType"/>
55
+ <complexType name="SignatureValueType">
56
+ <simpleContent>
57
+ <extension base="base64Binary">
58
+ <attribute name="Id" type="ID" use="optional"/>
59
+ </extension>
60
+ </simpleContent>
61
+ </complexType>
62
+
63
+ <!-- Start SignedInfo -->
64
+
65
+ <element name="SignedInfo" type="ds:SignedInfoType"/>
66
+ <complexType name="SignedInfoType">
67
+ <sequence>
68
+ <element ref="ds:CanonicalizationMethod"/>
69
+ <element ref="ds:SignatureMethod"/>
70
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
71
+ </sequence>
72
+ <attribute name="Id" type="ID" use="optional"/>
73
+ </complexType>
74
+
75
+ <element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
76
+ <complexType name="CanonicalizationMethodType" mixed="true">
77
+ <sequence>
78
+ <any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
79
+ <!-- (0,unbounded) elements from (1,1) namespace -->
80
+ </sequence>
81
+ <attribute name="Algorithm" type="anyURI" use="required"/>
82
+ </complexType>
83
+
84
+ <element name="SignatureMethod" type="ds:SignatureMethodType"/>
85
+ <complexType name="SignatureMethodType" mixed="true">
86
+ <sequence>
87
+ <element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
88
+ <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
89
+ <!-- (0,unbounded) elements from (1,1) external namespace -->
90
+ </sequence>
91
+ <attribute name="Algorithm" type="anyURI" use="required"/>
92
+ </complexType>
93
+
94
+ <!-- Start Reference -->
95
+
96
+ <element name="Reference" type="ds:ReferenceType"/>
97
+ <complexType name="ReferenceType">
98
+ <sequence>
99
+ <element ref="ds:Transforms" minOccurs="0"/>
100
+ <element ref="ds:DigestMethod"/>
101
+ <element ref="ds:DigestValue"/>
102
+ </sequence>
103
+ <attribute name="Id" type="ID" use="optional"/>
104
+ <attribute name="URI" type="anyURI" use="optional"/>
105
+ <attribute name="Type" type="anyURI" use="optional"/>
106
+ </complexType>
107
+
108
+ <element name="Transforms" type="ds:TransformsType"/>
109
+ <complexType name="TransformsType">
110
+ <sequence>
111
+ <element ref="ds:Transform" maxOccurs="unbounded"/>
112
+ </sequence>
113
+ </complexType>
114
+
115
+ <element name="Transform" type="ds:TransformType"/>
116
+ <complexType name="TransformType" mixed="true">
117
+ <choice minOccurs="0" maxOccurs="unbounded">
118
+ <any namespace="##other" processContents="lax"/>
119
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
120
+ <element name="XPath" type="string"/>
121
+ </choice>
122
+ <attribute name="Algorithm" type="anyURI" use="required"/>
123
+ </complexType>
124
+
125
+ <!-- End Reference -->
126
+
127
+ <element name="DigestMethod" type="ds:DigestMethodType"/>
128
+ <complexType name="DigestMethodType" mixed="true">
129
+ <sequence>
130
+ <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
131
+ </sequence>
132
+ <attribute name="Algorithm" type="anyURI" use="required"/>
133
+ </complexType>
134
+
135
+ <element name="DigestValue" type="ds:DigestValueType"/>
136
+ <simpleType name="DigestValueType">
137
+ <restriction base="base64Binary"/>
138
+ </simpleType>
139
+
140
+ <!-- End SignedInfo -->
141
+
142
+ <!-- Start KeyInfo -->
143
+
144
+ <element name="KeyInfo" type="ds:KeyInfoType"/>
145
+ <complexType name="KeyInfoType" mixed="true">
146
+ <choice maxOccurs="unbounded">
147
+ <element ref="ds:KeyName"/>
148
+ <element ref="ds:KeyValue"/>
149
+ <element ref="ds:RetrievalMethod"/>
150
+ <element ref="ds:X509Data"/>
151
+ <element ref="ds:PGPData"/>
152
+ <element ref="ds:SPKIData"/>
153
+ <element ref="ds:MgmtData"/>
154
+ <any processContents="lax" namespace="##other"/>
155
+ <!-- (1,1) elements from (0,unbounded) namespaces -->
156
+ </choice>
157
+ <attribute name="Id" type="ID" use="optional"/>
158
+ </complexType>
159
+
160
+ <element name="KeyName" type="string"/>
161
+ <element name="MgmtData" type="string"/>
162
+
163
+ <element name="KeyValue" type="ds:KeyValueType"/>
164
+ <complexType name="KeyValueType" mixed="true">
165
+ <choice>
166
+ <element ref="ds:DSAKeyValue"/>
167
+ <element ref="ds:RSAKeyValue"/>
168
+ <any namespace="##other" processContents="lax"/>
169
+ </choice>
170
+ </complexType>
171
+
172
+ <element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
173
+ <complexType name="RetrievalMethodType">
174
+ <sequence>
175
+ <element ref="ds:Transforms" minOccurs="0"/>
176
+ </sequence>
177
+ <attribute name="URI" type="anyURI"/>
178
+ <attribute name="Type" type="anyURI" use="optional"/>
179
+ </complexType>
180
+
181
+ <!-- Start X509Data -->
182
+
183
+ <element name="X509Data" type="ds:X509DataType"/>
184
+ <complexType name="X509DataType">
185
+ <sequence maxOccurs="unbounded">
186
+ <choice>
187
+ <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
188
+ <element name="X509SKI" type="base64Binary"/>
189
+ <element name="X509SubjectName" type="string"/>
190
+ <element name="X509Certificate" type="base64Binary"/>
191
+ <element name="X509CRL" type="base64Binary"/>
192
+ <any namespace="##other" processContents="lax"/>
193
+ </choice>
194
+ </sequence>
195
+ </complexType>
196
+
197
+ <complexType name="X509IssuerSerialType">
198
+ <sequence>
199
+ <element name="X509IssuerName" type="string"/>
200
+ <element name="X509SerialNumber" type="integer"/>
201
+ </sequence>
202
+ </complexType>
203
+
204
+ <!-- End X509Data -->
205
+
206
+ <!-- Begin PGPData -->
207
+
208
+ <element name="PGPData" type="ds:PGPDataType"/>
209
+ <complexType name="PGPDataType">
210
+ <choice>
211
+ <sequence>
212
+ <element name="PGPKeyID" type="base64Binary"/>
213
+ <element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
214
+ <any namespace="##other" processContents="lax" minOccurs="0"
215
+ maxOccurs="unbounded"/>
216
+ </sequence>
217
+ <sequence>
218
+ <element name="PGPKeyPacket" type="base64Binary"/>
219
+ <any namespace="##other" processContents="lax" minOccurs="0"
220
+ maxOccurs="unbounded"/>
221
+ </sequence>
222
+ </choice>
223
+ </complexType>
224
+
225
+ <!-- End PGPData -->
226
+
227
+ <!-- Begin SPKIData -->
228
+
229
+ <element name="SPKIData" type="ds:SPKIDataType"/>
230
+ <complexType name="SPKIDataType">
231
+ <sequence maxOccurs="unbounded">
232
+ <element name="SPKISexp" type="base64Binary"/>
233
+ <any namespace="##other" processContents="lax" minOccurs="0"/>
234
+ </sequence>
235
+ </complexType>
236
+
237
+ <!-- End SPKIData -->
238
+
239
+ <!-- End KeyInfo -->
240
+
241
+ <!-- Start Object (Manifest, SignatureProperty) -->
242
+
243
+ <element name="Object" type="ds:ObjectType"/>
244
+ <complexType name="ObjectType" mixed="true">
245
+ <sequence minOccurs="0" maxOccurs="unbounded">
246
+ <any namespace="##any" processContents="lax"/>
247
+ </sequence>
248
+ <attribute name="Id" type="ID" use="optional"/>
249
+ <attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
250
+ <attribute name="Encoding" type="anyURI" use="optional"/>
251
+ </complexType>
252
+
253
+ <element name="Manifest" type="ds:ManifestType"/>
254
+ <complexType name="ManifestType">
255
+ <sequence>
256
+ <element ref="ds:Reference" maxOccurs="unbounded"/>
257
+ </sequence>
258
+ <attribute name="Id" type="ID" use="optional"/>
259
+ </complexType>
260
+
261
+ <element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
262
+ <complexType name="SignaturePropertiesType">
263
+ <sequence>
264
+ <element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
265
+ </sequence>
266
+ <attribute name="Id" type="ID" use="optional"/>
267
+ </complexType>
268
+
269
+ <element name="SignatureProperty" type="ds:SignaturePropertyType"/>
270
+ <complexType name="SignaturePropertyType" mixed="true">
271
+ <choice maxOccurs="unbounded">
272
+ <any namespace="##other" processContents="lax"/>
273
+ <!-- (1,1) elements from (1,unbounded) namespaces -->
274
+ </choice>
275
+ <attribute name="Target" type="anyURI" use="required"/>
276
+ <attribute name="Id" type="ID" use="optional"/>
277
+ </complexType>
278
+
279
+ <!-- End Object (Manifest, SignatureProperty) -->
280
+
281
+ <!-- Start Algorithm Parameters -->
282
+
283
+ <simpleType name="HMACOutputLengthType">
284
+ <restriction base="integer"/>
285
+ </simpleType>
286
+
287
+ <!-- Start KeyValue Element-types -->
288
+
289
+ <element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
290
+ <complexType name="DSAKeyValueType">
291
+ <sequence>
292
+ <sequence minOccurs="0">
293
+ <element name="P" type="ds:CryptoBinary"/>
294
+ <element name="Q" type="ds:CryptoBinary"/>
295
+ </sequence>
296
+ <element name="G" type="ds:CryptoBinary" minOccurs="0"/>
297
+ <element name="Y" type="ds:CryptoBinary"/>
298
+ <element name="J" type="ds:CryptoBinary" minOccurs="0"/>
299
+ <sequence minOccurs="0">
300
+ <element name="Seed" type="ds:CryptoBinary"/>
301
+ <element name="PgenCounter" type="ds:CryptoBinary"/>
302
+ </sequence>
303
+ </sequence>
304
+ </complexType>
305
+
306
+ <element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
307
+ <complexType name="RSAKeyValueType">
308
+ <sequence>
309
+ <element name="Modulus" type="ds:CryptoBinary"/>
310
+ <element name="Exponent" type="ds:CryptoBinary"/>
311
+ </sequence>
312
+ </complexType>
313
+
314
+ <!-- End KeyValue Element-types -->
315
+
316
+ <!-- End Signature -->
317
+
318
+ </schema>
@@ -0,0 +1,12 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIBrTCCAaGgAwIBAgIBATADBgEAMGcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD
3
+ YWxpZm9ybmlhMRUwEwYDVQQHDAxTYW50YSBNb25pY2ExETAPBgNVBAoMCE9uZUxv
4
+ Z2luMRkwFwYDVQQDDBBhcHAub25lbG9naW4uY29tMB4XDTEwMTAxMTIxMTUxMloX
5
+ DTE1MTAxMTIxMTUxMlowZzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju
6
+ aWExFTATBgNVBAcMDFNhbnRhIE1vbmljYTERMA8GA1UECgwIT25lTG9naW4xGTAX
7
+ BgNVBAMMEGFwcC5vbmVsb2dpbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
8
+ AoGBAMPmjfjy7L35oDpeBXBoRVCgktPkLno9DOEWB7MgYMMVKs2B6ymWQLEWrDug
9
+ MK1hkzWFhIb5fqWLGbWy0J0veGR9/gHOQG+rD/I36xAXnkdiXXhzoiAG/zQxM0ed
10
+ MOUf40n314FC8moErcUg6QabttzesO59HFz6shPuxcWaVAgxAgMBAAEwAwYBAAMB
11
+ AA==
12
+ -----END CERTIFICATE-----
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
+
3
+ class RequestTest < Test::Unit::TestCase
4
+
5
+ context "Logoutrequest" do
6
+ settings = Cie::Saml::Settings.new
7
+
8
+ should "create the deflated SAMLRequest URL parameter" do
9
+ settings.idp_slo_target_url = "http://unauth.com/logout"
10
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings)
11
+ assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLRequest=/
12
+
13
+ inflated = decode_saml_request_payload(unauth_url)
14
+
15
+ assert_match /^<samlp:LogoutRequest/, inflated
16
+ end
17
+
18
+ should "support additional params" do
19
+
20
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings, { :hello => nil })
21
+ assert unauth_url =~ /&hello=$/
22
+
23
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings, { :foo => "bar" })
24
+ assert unauth_url =~ /&foo=bar$/
25
+ end
26
+
27
+ should "set sessionindex" do
28
+ settings.idp_slo_target_url = "http://example.com"
29
+ sessionidx = UUID.new.generate
30
+ settings.sessionindex = sessionidx
31
+
32
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings, { :name_id => "there" })
33
+ inflated = decode_saml_request_payload(unauth_url)
34
+
35
+ assert_match /<samlp:SessionIndex/, inflated
36
+ assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
37
+ end
38
+
39
+ should "set name_identifier_value" do
40
+ settings = Cie::Saml::Settings.new
41
+ settings.idp_slo_target_url = "http://example.com"
42
+ settings.name_identifier_format = "transient"
43
+ name_identifier_value = "abc123"
44
+ settings.name_identifier_value = name_identifier_value
45
+
46
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings, { :name_id => "there" })
47
+ inflated = decode_saml_request_payload(unauth_url)
48
+
49
+ assert_match /<saml:NameID/, inflated
50
+ assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
51
+ end
52
+
53
+ context "when the target url doesn't contain a query string" do
54
+ should "create the SAMLRequest parameter correctly" do
55
+ settings = Cie::Saml::Settings.new
56
+ settings.idp_slo_target_url = "http://example.com"
57
+
58
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings)
59
+ assert unauth_url =~ /^http:\/\/example.com\?SAMLRequest/
60
+ end
61
+ end
62
+
63
+ context "when the target url contains a query string" do
64
+ should "create the SAMLRequest parameter correctly" do
65
+ settings = Cie::Saml::Settings.new
66
+ settings.idp_slo_target_url = "http://example.com?field=value"
67
+
68
+ unauth_url = Cie::Saml::Logoutrequest.new.create(settings)
69
+ assert unauth_url =~ /^http:\/\/example.com\?field=value&SAMLRequest/
70
+ end
71
+ end
72
+
73
+ context "consumation of logout may need to track the transaction" do
74
+ should "have access to the request uuid" do
75
+ settings = Cie::Saml::Settings.new
76
+ settings.idp_slo_target_url = "http://example.com?field=value"
77
+
78
+ unauth_req = Cie::Saml::Logoutrequest.new
79
+ unauth_url = unauth_req.create(settings)
80
+
81
+ inflated = decode_saml_request_payload(unauth_url)
82
+ assert_match %r[ID='#{unauth_req.uuid}'], inflated
83
+ end
84
+ end
85
+ end
86
+
87
+ def decode_saml_request_payload(unauth_url)
88
+ payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
89
+ decoded = Base64.decode64(payload)
90
+
91
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
92
+ inflated = zstream.inflate(decoded)
93
+ zstream.finish
94
+ zstream.close
95
+ inflated
96
+ end
97
+
98
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
+
3
+ class RequestTest < Test::Unit::TestCase
4
+
5
+ context "Authrequest" do
6
+ should "create the deflated SAMLRequest URL parameter" do
7
+ settings = Cie::Saml::Settings.new
8
+ settings.idp_sso_target_url = "http://example.com"
9
+ auth_url = Cie::Saml::Authrequest.new.create(settings)
10
+ assert auth_url =~ /^http:\/\/example\.com\?SAMLRequest=/
11
+ payload = CGI.unescape(auth_url.split("=").last)
12
+ decoded = Base64.decode64(payload)
13
+
14
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
15
+ inflated = zstream.inflate(decoded)
16
+ zstream.finish
17
+ zstream.close
18
+
19
+ assert_match /^<samlp:AuthnRequest/, inflated
20
+ end
21
+
22
+ should "accept extra parameters" do
23
+ settings = Cie::Saml::Settings.new
24
+ settings.idp_sso_target_url = "http://example.com"
25
+
26
+ auth_url = Cie::Saml::Authrequest.new.create(settings, { :hello => "there" })
27
+ assert auth_url =~ /&hello=there$/
28
+
29
+ auth_url = Cie::Saml::Authrequest.new.create(settings, { :hello => nil })
30
+ assert auth_url =~ /&hello=$/
31
+ end
32
+
33
+ context "when the target url doesn't contain a query string" do
34
+ should "create the SAMLRequest parameter correctly" do
35
+ settings = Cie::Saml::Settings.new
36
+ settings.idp_sso_target_url = "http://example.com"
37
+
38
+ auth_url = Cie::Saml::Authrequest.new.create(settings)
39
+ assert auth_url =~ /^http:\/\/example.com\?SAMLRequest/
40
+ end
41
+ end
42
+
43
+ context "when the target url contains a query string" do
44
+ should "create the SAMLRequest parameter correctly" do
45
+ settings = Cie::Saml::Settings.new
46
+ settings.idp_sso_target_url = "http://example.com?field=value"
47
+
48
+ auth_url = Cie::Saml::Authrequest.new.create(settings)
49
+ assert auth_url =~ /^http:\/\/example.com\?field=value&SAMLRequest/
50
+ end
51
+ end
52
+ end
53
+ end