ruby-saml 0.8.16 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-saml might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +1 -6
- data/Gemfile +2 -12
- data/README.md +363 -35
- data/Rakefile +14 -0
- data/changelog.md +22 -9
- data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
- data/lib/onelogin/ruby-saml/attributes.rb +26 -64
- data/lib/onelogin/ruby-saml/authrequest.rb +47 -89
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
- data/lib/onelogin/ruby-saml/logoutrequest.rb +34 -93
- data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -24
- data/lib/onelogin/ruby-saml/metadata.rb +46 -16
- data/lib/onelogin/ruby-saml/response.rb +62 -322
- data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
- data/lib/onelogin/ruby-saml/settings.rb +54 -121
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +26 -61
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -84
- data/lib/onelogin/ruby-saml/utils.rb +32 -199
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/ruby-saml.rb +5 -2
- data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
- data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
- data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
- data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
- data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
- data/lib/schemas/sstc-metadata-attr.xsd +35 -0
- data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
- data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
- data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
- data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
- data/lib/schemas/xml.xsd +287 -0
- data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
- data/lib/xml_security.rb +83 -235
- data/ruby-saml.gemspec +1 -0
- data/test/idp_metadata_parser_test.rb +54 -0
- data/test/logoutrequest_test.rb +68 -144
- data/test/logoutresponse_test.rb +43 -25
- data/test/metadata_test.rb +87 -0
- data/test/request_test.rb +103 -90
- data/test/response_test.rb +181 -471
- data/test/responses/idp_descriptor.xml +3 -0
- data/test/responses/logoutresponse_fixtures.rb +5 -5
- data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
- data/test/responses/response_with_multiple_attribute_values.xml +1 -1
- data/test/responses/slo_request.xml +4 -0
- data/test/settings_test.rb +25 -112
- data/test/slo_logoutrequest_test.rb +41 -44
- data/test/slo_logoutresponse_test.rb +87 -167
- data/test/test_helper.rb +27 -102
- data/test/xml_security_test.rb +114 -337
- metadata +34 -84
- data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
- data/test/certificates/certificate.der +0 -0
- data/test/certificates/formatted_certificate +0 -14
- data/test/certificates/formatted_chained_certificate +0 -42
- data/test/certificates/formatted_private_key +0 -12
- data/test/certificates/formatted_rsa_private_key +0 -12
- data/test/certificates/invalid_certificate1 +0 -1
- data/test/certificates/invalid_certificate2 +0 -1
- data/test/certificates/invalid_certificate3 +0 -12
- data/test/certificates/invalid_chained_certificate1 +0 -1
- data/test/certificates/invalid_private_key1 +0 -1
- data/test/certificates/invalid_private_key2 +0 -1
- data/test/certificates/invalid_private_key3 +0 -10
- data/test/certificates/invalid_rsa_private_key1 +0 -1
- data/test/certificates/invalid_rsa_private_key2 +0 -1
- data/test/certificates/invalid_rsa_private_key3 +0 -10
- data/test/certificates/ruby-saml-2.crt +0 -15
- data/test/requests/logoutrequest_fixtures.rb +0 -47
- data/test/responses/encrypted_new_attack.xml.base64 +0 -1
- data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
- data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
- data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
- data/test/responses/invalids/no_signature.xml.base64 +0 -1
- data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
- data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
- data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
- data/test/responses/response_node_text_attack.xml.base64 +0 -1
- data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
- data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
- data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
- data/test/responses/response_with_signed_assertion_3.xml +0 -30
- data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
- data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
- data/test/responses/response_wrapped.xml.base64 +0 -150
- data/test/responses/valid_response.xml.base64 +0 -1
- data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
- data/test/utils_test.rb +0 -231
@@ -0,0 +1,3 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<md:EntityDescriptor entityID="https://example.hello.com/access/saml/idp.xml" validUntil="2014-04-17T18:02:33.910Z" xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"><md:IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"><md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxekNDQXhTZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBRENCaGpFTE1Ba0dBMVVFQmhNQ1FWVXgKRERBS0JnTlZCQWdUQTA1VFZ6RVBNQTBHQTFVRUJ4TUdVM2xrYm1WNU1Rd3dDZ1lEVlFRS0RBTlFTVlF4Q1RBSApCZ05WQkFzTUFERVlNQllHQTFVRUF3d1BiR0YzY21WdVkyVndhWFF1WTI5dE1TVXdJd1lKS29aSWh2Y05BUWtCCkRCWnNZWGR5Wlc1alpTNXdhWFJBWjIxaGFXd3VZMjl0TUI0WERURXlNRFF4T1RJeU5UUXhPRm9YRFRNeU1EUXgKTkRJeU5UUXhPRm93Z1lZeEN6QUpCZ05WQkFZVEFrRlZNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVApCbE41Wkc1bGVURU1NQW9HQTFVRUNnd0RVRWxVTVFrd0J3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psCmJtTmxjR2wwTG1OdmJURWxNQ01HQ1NxR1NJYjNEUUVKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnYKYlRDQm56QU5CZ2txaGtpRzl3MEJBUUVGQUFPQmpRQXdnWWtDZ1lFQXFqaWUzUjJvaStwRGFldndJeXMvbWJVVApubkdsa3h0ZGlrcnExMXZleHd4SmlQTmhtaHFSVzNtVXVKRXpsbElkVkw2RW14R1lUcXBxZjkzSGxoa3NhZUowCjhVZ2pQOVVtTVlyaFZKdTFqY0ZXVjdmei9yKzIxL2F3VG5EVjlzTVlRcXVJUllZeTdiRzByMU9iaXdkb3ZudGsKN2dGSTA2WjB2WmFjREU1Ym9xVUNBd0VBQWFPQ0FTVXdnZ0VoTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRRApBZ1VnTUIwR0ExVWREZ1FXQkJTUk9OOEdKOG8rOGpnRnRqa3R3WmRxeDZCUnlUQVRCZ05WSFNVRUREQUtCZ2dyCkJnRUZCUWNEQVRBZEJnbGdoa2dCaHZoQ0FRMEVFQllPVkdWemRDQllOVEE1SUdObGNuUXdnYk1HQTFVZEl3U0IKcXpDQnFJQVVrVGpmQmlmS1B2STRCYlk1TGNHWGFzZWdVY21oZ1l5a2dZa3dnWVl4Q3pBSkJnTlZCQVlUQWtGVgpNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVEJsTjVaRzVsZVRFTU1Bb0dBMVVFQ2d3RFVFbFVNUWt3CkJ3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psYm1ObGNHbDBMbU52YlRFbE1DTUdDU3FHU0liM0RRRUoKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnZiWUlCQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9CZ1FDRQpUQWVKVERTQVc2ejFVRlRWN1FyZWg0VUxGT1JhajkrZUN1RjNLV0RIYyswSVFDajlyZG5ERzRRL3dmNy9yYVEwCkpuUFFDU0NkclBMSmV5b1BIN1FhVHdvYUY3ZHpWdzRMQ3N5TkpURld4NGNNNTBWdzZSNWZET2dpQzhic2ZmUzgKQkptb3VscnJaRE5OVmpHOG1XNmNMeHJZdlZRT3JSVmVjQ0ZJZ3NzQ2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
3
|
+
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURxekNDQXhTZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBRENCaGpFTE1Ba0dBMVVFQmhNQ1FWVXgKRERBS0JnTlZCQWdUQTA1VFZ6RVBNQTBHQTFVRUJ4TUdVM2xrYm1WNU1Rd3dDZ1lEVlFRS0RBTlFTVlF4Q1RBSApCZ05WQkFzTUFERVlNQllHQTFVRUF3d1BiR0YzY21WdVkyVndhWFF1WTI5dE1TVXdJd1lKS29aSWh2Y05BUWtCCkRCWnNZWGR5Wlc1alpTNXdhWFJBWjIxaGFXd3VZMjl0TUI0WERURXlNRFF4T1RJeU5UUXhPRm9YRFRNeU1EUXgKTkRJeU5UUXhPRm93Z1lZeEN6QUpCZ05WQkFZVEFrRlZNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVApCbE41Wkc1bGVURU1NQW9HQTFVRUNnd0RVRWxVTVFrd0J3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psCmJtTmxjR2wwTG1OdmJURWxNQ01HQ1NxR1NJYjNEUUVKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnYKYlRDQm56QU5CZ2txaGtpRzl3MEJBUUVGQUFPQmpRQXdnWWtDZ1lFQXFqaWUzUjJvaStwRGFldndJeXMvbWJVVApubkdsa3h0ZGlrcnExMXZleHd4SmlQTmhtaHFSVzNtVXVKRXpsbElkVkw2RW14R1lUcXBxZjkzSGxoa3NhZUowCjhVZ2pQOVVtTVlyaFZKdTFqY0ZXVjdmei9yKzIxL2F3VG5EVjlzTVlRcXVJUllZeTdiRzByMU9iaXdkb3ZudGsKN2dGSTA2WjB2WmFjREU1Ym9xVUNBd0VBQWFPQ0FTVXdnZ0VoTUFrR0ExVWRFd1FDTUFBd0N3WURWUjBQQkFRRApBZ1VnTUIwR0ExVWREZ1FXQkJTUk9OOEdKOG8rOGpnRnRqa3R3WmRxeDZCUnlUQVRCZ05WSFNVRUREQUtCZ2dyCkJnRUZCUWNEQVRBZEJnbGdoa2dCaHZoQ0FRMEVFQllPVkdWemRDQllOVEE1SUdObGNuUXdnYk1HQTFVZEl3U0IKcXpDQnFJQVVrVGpmQmlmS1B2STRCYlk1TGNHWGFzZWdVY21oZ1l5a2dZa3dnWVl4Q3pBSkJnTlZCQVlUQWtGVgpNUXd3Q2dZRFZRUUlFd05PVTFjeER6QU5CZ05WQkFjVEJsTjVaRzVsZVRFTU1Bb0dBMVVFQ2d3RFVFbFVNUWt3CkJ3WURWUVFMREFBeEdEQVdCZ05WQkFNTUQyeGhkM0psYm1ObGNHbDBMbU52YlRFbE1DTUdDU3FHU0liM0RRRUoKQVF3V2JHRjNjbVZ1WTJVdWNHbDBRR2R0WVdsc0xtTnZiWUlCQVRBTkJna3Foa2lHOXcwQkFRc0ZBQU9CZ1FDRQpUQWVKVERTQVc2ejFVRlRWN1FyZWg0VUxGT1JhajkrZUN1RjNLV0RIYyswSVFDajlyZG5ERzRRL3dmNy9yYVEwCkpuUFFDU0NkclBMSmV5b1BIN1FhVHdvYUY3ZHpWdzRMQ3N5TkpURld4NGNNNTBWdzZSNWZET2dpQzhic2ZmUzgKQkptb3VscnJaRE5OVmpHOG1XNmNMeHJZdlZRT3JSVmVjQ0ZJZ3NzQ2JBPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.hello.com/access/saml/logout" ResponseLocation="https://example.hello.com/access/saml/logout"/><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat><md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://example.hello.com/access/saml/login"/></md:IDPSSODescriptor></md:EntityDescriptor>
|
@@ -15,9 +15,9 @@ def valid_response(opts = {})
|
|
15
15
|
xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
16
16
|
ID=\"#{random_id}\" Version=\"2.0\"
|
17
17
|
IssueInstant=\"#{opts[:issue_instant]}\"
|
18
|
-
Destination=\"#{opts[:settings].
|
18
|
+
Destination=\"#{opts[:settings].single_logout_service_url}\"
|
19
19
|
InResponseTo=\"#{opts[:uuid]}\">
|
20
|
-
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].
|
20
|
+
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].issuer}</saml:Issuer>
|
21
21
|
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
22
22
|
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
23
23
|
Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\">
|
@@ -33,9 +33,9 @@ def unsuccessful_response(opts = {})
|
|
33
33
|
xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
34
34
|
ID=\"#{random_id}\" Version=\"2.0\"
|
35
35
|
IssueInstant=\"#{opts[:issue_instant]}\"
|
36
|
-
Destination=\"#{opts[:settings].
|
36
|
+
Destination=\"#{opts[:settings].single_logout_service_url}\"
|
37
37
|
InResponseTo=\"#{opts[:uuid]}\">
|
38
|
-
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].
|
38
|
+
<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].issuer}</saml:Issuer>
|
39
39
|
<samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
|
40
40
|
<samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
|
41
41
|
Value=\"urn:oasis:names:tc:SAML:2.0:status:Requester\">
|
@@ -56,7 +56,7 @@ def settings
|
|
56
56
|
{
|
57
57
|
:assertion_consumer_service_url => "http://app.muda.no/sso/consume",
|
58
58
|
:single_logout_service_url => "http://app.muda.no/sso/consume_logout",
|
59
|
-
:
|
59
|
+
:issuer => "http://app.muda.no",
|
60
60
|
:sp_name_qualifier => "http://sso.muda.no",
|
61
61
|
:idp_sso_target_url => "http://sso.muda.no/sso",
|
62
62
|
:idp_slo_target_url => "http://sso.muda.no/slo",
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://vmwdemo.socialcast.com/saml/authenticate" ID="_f9fbcbf79715244c7ff909d8663d782e" InResponseTo="_4b4c72d0-eb5a-0131-0fec-0050568312b8" IssueInstant="2014-07-11T18:53:30.916Z" Version="2.0"><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_fddb13c899036a90f920ddaac50fc0d6" IssueInstant="2014-07-11T18:53:30.916Z" Version="2.0"><saml:Issuer>https://hw6dldc.vmwdemo.com/SAAS/API/1.0/GET/metadata/idp.xml</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
2
|
+
<ds:SignedInfo>
|
3
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
4
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
5
|
+
<ds:Reference URI="#_fddb13c899036a90f920ddaac50fc0d6">
|
6
|
+
<ds:Transforms>
|
7
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
8
|
+
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="ds saml xenc xs xsi"/></ds:Transform>
|
9
|
+
</ds:Transforms>
|
10
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
11
|
+
<ds:DigestValue>HS49Xqi+JftXvslmp/boT9ixzp8=</ds:DigestValue>
|
12
|
+
</ds:Reference>
|
13
|
+
</ds:SignedInfo>
|
14
|
+
<ds:SignatureValue>
|
15
|
+
gdY9y3GNOgOqBOlEx981yILKAssUG79fXw639MJB3uJjLYokqY+Y5KFFtAU4FGvh/L6Romghx0is
|
16
|
+
rxukFkfw9coxKOhCoDZiaYPvvuC2qqhTwTAZ0Spvwuffrj3UwztSWbS6JGXtebo4ghKnae4hH5lF
|
17
|
+
tRawV9HnbLJmhL3cVPSu+7SF3iWov0PZyZczH1P6sZrYeX5X32h3RhXXxMi3kgHGWxaVTQmgTEgu
|
18
|
+
xN3GD7lnsf+WOAvdPAPgFrJjEGJZDd/MClS/x5ZwLnMZ82r7XHoFhiC47eq3Te+JE9qZvSbIs/om
|
19
|
+
dpuFSaFKxxdM8C+vHTRUDDaGckqckPc5Y7wlgA==
|
20
|
+
</ds:SignatureValue>
|
21
|
+
</ds:Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="https://hw6dldc.vmwdemo.com/SAAS/API/1.0/GET/metadata/idp.xml">akjoshi87+du@gmail.com</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData InResponseTo="_4b4c72d0-eb5a-0131-0fec-0050568312b8" NotOnOrAfter="2014-07-11T18:56:50.916Z" Recipient="https://vmwdemo.socialcast.com/saml/authenticate"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2014-07-11T18:53:15.916Z" NotOnOrAfter="2014-07-11T18:56:50.916Z"><saml:AudienceRestriction><saml:Audience>vmwdemo.socialcast.com</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2014-07-11T18:53:30.916Z" SessionIndex="_876ca8142c7ba8126af3c90d952af251"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement><saml:Attribute Name="first_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Demo</saml:AttributeValue></saml:Attribute><saml:Attribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">akjoshi87+du@gmail.com</saml:AttributeValue></saml:Attribute><saml:Attribute Name="last_name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"><saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">User</saml:AttributeValue></saml:Attribute><saml:EncryptedAttribute><xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_2a1c0500932ae79e9f5ede82dccb57c6" Type="http://www.w3.org/2001/04/xmlenc#Element"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><xenc:EncryptedKey Id="_ff2d29836cd453cdfca94b69b630cf40"><xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/><xenc:CipherData><xenc:CipherValue>IdFfvxdt+YBaLSkWfcxuGqiPDyiQtpklGkJZFW+UoZXMhopZXmW/ekfEAf1VpzIlDlo3xwY2y8Rw
|
22
|
+
zZwASwjiuHoQSMZQzZ6Ws184f1pWh9un23wgHzYc/jwXF0pXfcVL944SSxxNO4zO+DMJz6Px9rvk
|
23
|
+
Rpac86uujfBuqXlo684=</xenc:CipherValue></xenc:CipherData></xenc:EncryptedKey></ds:KeyInfo><xenc:CipherData><xenc:CipherValue>/+Noi1tNN1HcY+bW/iyBkwOYR4X32pTPzq7EjQO/HB3L0B2RtpsYkvC9750eb6KydbsBSGCyNt3k
|
24
|
+
grjcI1nUgvvY488NhIo9+PWv3MhAqnljKhDzl6AcfE00Lq3HA1FcTCwrE0VLjUV4NtztK2JVCZwu
|
25
|
+
ToViUJMlu1SGL8U7uRfsRpbrXoIEv1AwFHjz+XZgwD3nxl79iAcnm3FFX7nIkjUQIPPBWC/U4XJN
|
26
|
+
u+u5svSoUpIOFqdeNcDQUq5+P5lXT46O5LcULQrEY8xHNGToxOwINMOrU+rCgwyAVbP/SaY9ywYe
|
27
|
+
bxpESNkHmkjLAI7GBvLRRkTEE88Q6/uV9D1A5X3rT4BMQJ0N7BfgnOJ7IMga2Q9wU9oPuoCsqL9I
|
28
|
+
bP9IY1vCLcAAEsMR0EgZaInLCiLoXdmDHllSo2fyKQqBGxE+KpZhvVdCOVzLN3+TrW3k/xl/kx6w
|
29
|
+
AIPFlXd6TRVzmg==</xenc:CipherValue></xenc:CipherData></xenc:EncryptedData></saml:EncryptedAttribute></saml:AttributeStatement></saml:Assertion></samlp:Response>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
<samlp:LogoutRequest Version='2.0' ID='_c0348950-935b-0131-1060-782bcb56fcaa' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol' IssueInstant='2014-03-21T19:20:13'>
|
2
|
+
<saml:Issuer xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>https://app.onelogin.com/saml/metadata/SOMEACCOUNT</saml:Issuer>
|
3
|
+
<saml:NameID xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion'>someone@example.org</saml:NameID>
|
4
|
+
</samlp:LogoutRequest>
|
data/test/settings_test.rb
CHANGED
@@ -1,18 +1,23 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
-
class SettingsTest <
|
3
|
+
class SettingsTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
context "Settings" do
|
6
|
+
setup do
|
7
7
|
@settings = OneLogin::RubySaml::Settings.new
|
8
8
|
end
|
9
|
-
|
9
|
+
should "should provide getters and settings" do
|
10
10
|
accessors = [
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
11
|
+
:idp_entity_id, :idp_sso_target_url, :idp_slo_target_url, :idp_cert, :idp_cert_fingerprint,
|
12
|
+
:issuer, :assertion_consumer_service_url, :assertion_consumer_service_binding,
|
13
|
+
:single_logout_service_url, :single_logout_service_binding,
|
14
|
+
:sp_name_qualifier, :name_identifier_format, :name_identifier_value,
|
15
|
+
:sessionindex, :attributes_index, :passive, :force_authn,
|
16
|
+
:compress_request, :double_quote_xml_attribute_values, :protocol_binding,
|
17
|
+
:security, :certificate, :private_key,
|
18
|
+
:authn_context, :authn_context_comparison, :authn_context_decl_ref,
|
19
|
+
:assertion_consumer_logout_service_url,
|
20
|
+
:assertion_consumer_logout_service_binding
|
16
21
|
]
|
17
22
|
|
18
23
|
accessors.each do |accessor|
|
@@ -20,9 +25,10 @@ class SettingsTest < Minitest::Test
|
|
20
25
|
@settings.send("#{accessor}=".to_sym, value)
|
21
26
|
assert_equal value, @settings.send(accessor)
|
22
27
|
end
|
28
|
+
|
23
29
|
end
|
24
30
|
|
25
|
-
|
31
|
+
should "create settings from hash" do
|
26
32
|
|
27
33
|
config = {
|
28
34
|
:assertion_consumer_service_url => "http://app.muda.no/sso",
|
@@ -32,6 +38,7 @@ class SettingsTest < Minitest::Test
|
|
32
38
|
:idp_slo_target_url => "http://sso.muda.no/slo",
|
33
39
|
:idp_cert_fingerprint => "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
|
34
40
|
:name_identifier_format => "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
|
41
|
+
:attributes_index => 30,
|
35
42
|
:passive => true,
|
36
43
|
:protocol_binding => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
|
37
44
|
}
|
@@ -42,110 +49,16 @@ class SettingsTest < Minitest::Test
|
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
it "returns nil when the cert is nil" do
|
52
|
-
@settings.idp_cert = nil
|
53
|
-
assert_nil @settings.get_idp_cert
|
54
|
-
end
|
55
|
-
|
56
|
-
it "returns the certificate when it is valid" do
|
57
|
-
@settings.idp_cert = ruby_saml_cert_text
|
58
|
-
assert @settings.get_idp_cert.kind_of? OpenSSL::X509::Certificate
|
59
|
-
end
|
60
|
-
|
61
|
-
it "raises when the certificate is not valid" do
|
62
|
-
# formatted but invalid cert
|
63
|
-
@settings.idp_cert = read_certificate("formatted_certificate")
|
64
|
-
assert_raises(OpenSSL::X509::CertificateError) {
|
65
|
-
@settings.get_idp_cert
|
66
|
-
}
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "#get_sp_cert" do
|
71
|
-
it "returns nil when the cert is an empty string" do
|
72
|
-
@settings.certificate = ""
|
73
|
-
assert_nil @settings.get_sp_cert
|
74
|
-
end
|
75
|
-
|
76
|
-
it "returns nil when the cert is nil" do
|
77
|
-
@settings.certificate = nil
|
78
|
-
assert_nil @settings.get_sp_cert
|
79
|
-
end
|
80
|
-
|
81
|
-
it "returns the certificate when it is valid" do
|
82
|
-
@settings.certificate = ruby_saml_cert_text
|
83
|
-
assert @settings.get_sp_cert.kind_of? OpenSSL::X509::Certificate
|
84
|
-
end
|
85
|
-
|
86
|
-
it "raises when the certificate is not valid" do
|
87
|
-
# formatted but invalid cert
|
88
|
-
@settings.certificate = read_certificate("formatted_certificate")
|
89
|
-
assert_raises(OpenSSL::X509::CertificateError) {
|
90
|
-
@settings.get_sp_cert
|
91
|
-
}
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe "#get_sp_key" do
|
96
|
-
it "returns nil when the private key is an empty string" do
|
97
|
-
@settings.private_key = ""
|
98
|
-
assert_nil @settings.get_sp_key
|
99
|
-
end
|
100
|
-
|
101
|
-
it "returns nil when the private key is nil" do
|
102
|
-
@settings.private_key = nil
|
103
|
-
assert_nil @settings.get_sp_key
|
104
|
-
end
|
105
|
-
|
106
|
-
it "returns the private key when it is valid" do
|
107
|
-
@settings.private_key = ruby_saml_key_text
|
108
|
-
assert @settings.get_sp_key.kind_of? OpenSSL::PKey::RSA
|
109
|
-
end
|
110
|
-
|
111
|
-
it "raises when the private key is not valid" do
|
112
|
-
# formatted but invalid rsa private key
|
113
|
-
@settings.private_key = read_certificate("formatted_rsa_private_key")
|
114
|
-
assert_raises(OpenSSL::PKey::RSAError) {
|
115
|
-
@settings.get_sp_key
|
116
|
-
}
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
|
121
|
-
describe "#get_fingerprint" do
|
122
|
-
it "get the fingerprint value when cert and fingerprint in settings are nil" do
|
123
|
-
@settings.idp_cert_fingerprint = nil
|
124
|
-
@settings.idp_cert = nil
|
125
|
-
fingerprint = @settings.get_fingerprint
|
126
|
-
assert_nil fingerprint
|
127
|
-
end
|
128
|
-
|
129
|
-
it "get the fingerprint value when there is a cert at the settings" do
|
130
|
-
@settings.idp_cert_fingerprint = nil
|
131
|
-
@settings.idp_cert = ruby_saml_cert_text
|
132
|
-
fingerprint = @settings.get_fingerprint
|
133
|
-
assert fingerprint.downcase == ruby_saml_cert_fingerprint.downcase
|
134
|
-
end
|
135
|
-
|
136
|
-
it "get the fingerprint value when there is a fingerprint at the settings" do
|
137
|
-
@settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
|
138
|
-
@settings.idp_cert = nil
|
139
|
-
fingerprint = @settings.get_fingerprint
|
140
|
-
assert fingerprint.downcase == ruby_saml_cert_fingerprint.downcase
|
52
|
+
should "configure attribute service attributes correctly" do
|
53
|
+
@settings = OneLogin::RubySaml::Settings.new
|
54
|
+
@settings.attribute_consuming_service.configure do
|
55
|
+
service_name "Test Service"
|
56
|
+
add_attribute :name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name"
|
141
57
|
end
|
142
58
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
fingerprint = @settings.get_fingerprint
|
147
|
-
assert fingerprint.downcase == ruby_saml_cert_fingerprint.downcase
|
148
|
-
end
|
59
|
+
assert_equal @settings.attribute_consuming_service.configured?, true
|
60
|
+
assert_equal @settings.attribute_consuming_service.name, "Test Service"
|
61
|
+
assert_equal @settings.attribute_consuming_service.attributes, [{:name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name" }]
|
149
62
|
end
|
150
63
|
|
151
64
|
end
|
@@ -1,64 +1,61 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
|
-
require
|
2
|
+
require 'responses/logoutresponse_fixtures'
|
3
3
|
|
4
|
-
class
|
4
|
+
class RubySamlTest < Test::Unit::TestCase
|
5
5
|
|
6
|
-
|
6
|
+
context "SloLogoutrequest" do
|
7
|
+
should "raise an exception when response is initialized with nil" do
|
8
|
+
assert_raises(ArgumentError) { OneLogin::RubySaml::SloLogoutrequest.new(nil) }
|
9
|
+
end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
context "#is_valid?" do
|
12
|
+
should "return false when response is initialized with blank data" do
|
13
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new('')
|
14
|
+
assert !request.is_valid?
|
11
15
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
|
17
|
+
should "return true when the request is initialized with valid data" do
|
18
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
19
|
+
assert request.is_valid?
|
20
|
+
assert_equal 'someone@example.org', request.name_id
|
15
21
|
end
|
16
|
-
|
17
|
-
|
18
|
-
|
22
|
+
|
23
|
+
should "should be idempotent when the response is initialized with invalid data" do
|
24
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(invalid_xml_response)
|
25
|
+
assert !request.is_valid?
|
26
|
+
assert !request.is_valid?
|
19
27
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
28
|
+
|
29
|
+
should "should be idempotent when the response is initialized with valid data" do
|
30
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
31
|
+
assert request.is_valid?
|
32
|
+
assert request.is_valid?
|
23
33
|
end
|
24
|
-
it "support base64 encoded requests" do
|
25
|
-
expected_request = valid_request
|
26
|
-
logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(Base64.encode64(expected_request), settings)
|
27
34
|
|
28
|
-
|
35
|
+
should "raise error for invalid xml" do
|
36
|
+
logout_request = OneLogin::RubySaml::SloLogoutrequest.new(invalid_xml_response)
|
37
|
+
assert_raises(OneLogin::RubySaml::ValidationError) { logout_request.validate! }
|
29
38
|
end
|
30
39
|
end
|
31
40
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request({:uuid => in_relation_to_request_id}), settings)
|
37
|
-
|
38
|
-
assert logoutrequest.validate
|
39
|
-
|
40
|
-
assert_equal settings.idp_entity_id, logoutrequest.issuer
|
41
|
-
|
42
|
-
assert_equal "testuser@example.com", logoutrequest.nameid
|
43
|
-
|
44
|
-
assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", logoutrequest.nameid_format
|
41
|
+
context "#name_id" do
|
42
|
+
should "extract the value of the name id element" do
|
43
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
44
|
+
assert_equal "someone@example.org", request.name_id
|
45
45
|
end
|
46
|
-
|
47
46
|
end
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request({:uuid => in_relation_to_request_id}), settings)
|
54
|
-
|
55
|
-
logoutrequest.validate!
|
48
|
+
context "#issuer" do
|
49
|
+
should "return the issuer inside the request" do
|
50
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
51
|
+
assert_equal "https://app.onelogin.com/saml/metadata/SOMEACCOUNT", request.issuer
|
56
52
|
end
|
53
|
+
end
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
context "#id" do
|
56
|
+
should "extract the value of the ID attribute" do
|
57
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
58
|
+
assert_equal "_c0348950-935b-0131-1060-782bcb56fcaa", request.id
|
62
59
|
end
|
63
60
|
end
|
64
61
|
|
@@ -1,226 +1,146 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
-
class SloLogoutresponseTest <
|
3
|
+
class SloLogoutresponseTest < Test::Unit::TestCase
|
4
4
|
|
5
|
-
|
5
|
+
context "SloLogoutresponse" do
|
6
|
+
settings = OneLogin::RubySaml::Settings.new
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
before do
|
8
|
+
should "create the deflated SAMLResponse URL parameter" do
|
10
9
|
settings.idp_slo_target_url = "http://unauth.com/logout"
|
11
10
|
settings.name_identifier_value = "f00f00"
|
12
11
|
settings.compress_request = true
|
13
|
-
settings.certificate = ruby_saml_cert_text
|
14
|
-
settings.private_key = ruby_saml_key_text
|
15
|
-
end
|
16
12
|
|
17
|
-
|
18
|
-
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings)
|
19
|
-
assert_match /^http:\/\/unauth\.com\/logout\?SAMLResponse=/, unauth_url
|
13
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
20
14
|
|
21
|
-
|
22
|
-
assert_match /^<samlp:LogoutResponse/, inflated
|
23
|
-
end
|
15
|
+
assert request.is_valid?
|
24
16
|
|
25
|
-
|
26
|
-
unauth_url
|
27
|
-
assert_match /&hello=$/, unauth_url
|
17
|
+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id)
|
18
|
+
assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLResponse=/
|
28
19
|
|
29
|
-
|
30
|
-
assert_match /&foo=bar$/, unauth_url
|
20
|
+
inflated = decode_saml_response_payload(unauth_url)
|
31
21
|
|
32
|
-
|
33
|
-
assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
|
22
|
+
assert_match /^<samlp:LogoutResponse/, inflated
|
34
23
|
end
|
35
24
|
|
36
|
-
|
37
|
-
|
38
|
-
|
25
|
+
should "support additional params" do
|
26
|
+
settings.idp_slo_target_url = "http://unauth.com/logout"
|
27
|
+
settings.name_identifier_value = "f00f00"
|
28
|
+
settings.compress_request = true
|
29
|
+
|
30
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
39
31
|
|
40
|
-
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings,
|
41
|
-
assert unauth_url
|
32
|
+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :hello => nil })
|
33
|
+
assert unauth_url =~ /&hello=$/
|
42
34
|
|
43
|
-
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings,
|
44
|
-
assert
|
35
|
+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :foo => "bar" })
|
36
|
+
assert unauth_url =~ /&foo=bar$/
|
45
37
|
|
46
|
-
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings,
|
47
|
-
assert unauth_url
|
38
|
+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :RelayState => "http://idp.example.com" })
|
39
|
+
assert unauth_url =~ /&RelayState=http%3A%2F%2Fidp.example.com$/
|
48
40
|
end
|
49
41
|
|
50
|
-
|
51
|
-
|
42
|
+
should "set InResponseTo to the ID from the logout request" do
|
43
|
+
settings.idp_slo_target_url = "http://unauth.com/logout"
|
44
|
+
settings.name_identifier_value = "f00f00"
|
45
|
+
settings.compress_request = true
|
46
|
+
|
47
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
48
|
+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id)
|
52
49
|
|
53
50
|
inflated = decode_saml_response_payload(unauth_url)
|
51
|
+
|
54
52
|
assert_match /InResponseTo='_c0348950-935b-0131-1060-782bcb56fcaa'/, inflated
|
55
53
|
end
|
56
54
|
|
57
|
-
|
58
|
-
|
55
|
+
should "set a custom successful logout message on the response" do
|
56
|
+
settings.idp_slo_target_url = "http://unauth.com/logout"
|
57
|
+
settings.name_identifier_value = "f00f00"
|
58
|
+
settings.compress_request = true
|
59
|
+
|
60
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
61
|
+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, "Custom Logout Message")
|
59
62
|
|
60
63
|
inflated = decode_saml_response_payload(unauth_url)
|
64
|
+
|
61
65
|
assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
|
62
66
|
end
|
63
67
|
|
64
|
-
|
65
|
-
|
66
|
-
|
68
|
+
context "when the settings indicate to sign (embebed) the logout response" do
|
69
|
+
should "create a signed logout response" do
|
70
|
+
settings = OneLogin::RubySaml::Settings.new
|
67
71
|
settings.compress_response = false
|
72
|
+
settings.idp_slo_target_url = "http://example.com?field=value"
|
68
73
|
settings.security[:logout_responses_signed] = true
|
69
74
|
settings.security[:embed_sign] = true
|
70
|
-
|
71
|
-
|
72
|
-
it "doesn't sign through create_xml_document" do
|
73
|
-
unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
|
74
|
-
inflated = unauth_res.create_xml_document(settings).to_s
|
75
|
-
|
76
|
-
refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
77
|
-
refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
78
|
-
refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
79
|
-
end
|
80
|
-
|
81
|
-
it "sign unsigned request" do
|
82
|
-
unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
|
83
|
-
unauth_res_doc = unauth_res.create_xml_document(settings)
|
84
|
-
inflated = unauth_res_doc.to_s
|
75
|
+
settings.certificate = ruby_saml_cert_text
|
76
|
+
settings.private_key = ruby_saml_key_text
|
85
77
|
|
86
|
-
|
87
|
-
|
88
|
-
refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
89
|
-
|
90
|
-
inflated = unauth_res.sign_document(unauth_res_doc, settings).to_s
|
91
|
-
|
92
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
93
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
94
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
95
|
-
end
|
96
|
-
|
97
|
-
it "signs through create_logout_response_xml_doc" do
|
98
|
-
unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
|
99
|
-
inflated = unauth_res.create_logout_response_xml_doc(settings).to_s
|
100
|
-
|
101
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
|
102
|
-
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
|
103
|
-
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
|
104
|
-
end
|
105
|
-
|
106
|
-
it "create a signed logout response" do
|
107
|
-
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
|
78
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
79
|
+
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
|
108
80
|
|
109
81
|
response_xml = Base64.decode64(params["SAMLResponse"])
|
110
82
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
111
|
-
|
112
|
-
|
83
|
+
response_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/
|
84
|
+
response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/
|
113
85
|
end
|
114
86
|
|
115
|
-
|
116
|
-
settings
|
117
|
-
settings.
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
123
|
-
assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/, response_xml
|
124
|
-
assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha256'\/>/, response_xml
|
125
|
-
end
|
126
|
-
|
127
|
-
it "create a signed logout response with 512 digest and signature method RSA_SHA384" do
|
128
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
|
87
|
+
should "create a signed logout response with 256 digest and signature methods" do
|
88
|
+
settings = OneLogin::RubySaml::Settings.new
|
89
|
+
settings.compress_response = false
|
90
|
+
settings.idp_slo_target_url = "http://example.com?field=value"
|
91
|
+
settings.security[:logout_responses_signed] = true
|
92
|
+
settings.security[:embed_sign] = true
|
93
|
+
settings.security[:signature_method] = XMLSecurity::Document::SHA256
|
129
94
|
settings.security[:digest_method] = XMLSecurity::Document::SHA512
|
95
|
+
settings.certificate = ruby_saml_cert_text
|
96
|
+
settings.private_key = ruby_saml_key_text
|
130
97
|
|
131
|
-
|
98
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
99
|
+
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
|
132
100
|
|
133
101
|
response_xml = Base64.decode64(params["SAMLResponse"])
|
134
102
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
135
|
-
|
136
|
-
|
103
|
+
response_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/
|
104
|
+
response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha512'\/>/
|
137
105
|
end
|
138
106
|
end
|
139
107
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
before do
|
108
|
+
context "when the settings indicate to sign the logout response" do
|
109
|
+
should "create a signature parameter" do
|
110
|
+
settings = OneLogin::RubySaml::Settings.new
|
145
111
|
settings.compress_response = false
|
112
|
+
settings.idp_slo_target_url = "http://example.com?field=value"
|
113
|
+
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
|
146
114
|
settings.security[:logout_responses_signed] = true
|
147
115
|
settings.security[:embed_sign] = false
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
152
|
-
|
153
|
-
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
|
154
|
-
assert params['SAMLResponse']
|
155
|
-
assert params[:RelayState]
|
156
|
-
assert params['Signature']
|
157
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
|
158
|
-
|
159
|
-
query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
|
160
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
161
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
162
|
-
|
163
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
164
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
|
165
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
166
|
-
end
|
116
|
+
settings.security[:signature_method] = XMLSecurity::Document::SHA1
|
117
|
+
settings.certificate = ruby_saml_cert_text
|
118
|
+
settings.private_key = ruby_saml_key_text
|
167
119
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
|
172
|
-
assert params['SAMLResponse']
|
173
|
-
assert params[:RelayState]
|
120
|
+
request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
121
|
+
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
|
174
122
|
assert params['Signature']
|
123
|
+
assert params['SigAlg'] == XMLSecurity::Document::SHA1
|
175
124
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
180
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
181
|
-
|
182
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
183
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
|
184
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
185
|
-
end
|
186
|
-
|
187
|
-
it "create a signature parameter with RSA_SHA384 / SHA384 and validate it" do
|
188
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
|
189
|
-
|
190
|
-
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
|
191
|
-
assert params['SAMLResponse']
|
192
|
-
assert params[:RelayState]
|
125
|
+
# signature_method only affects the embedeed signature
|
126
|
+
settings.security[:signature_method] = XMLSecurity::Document::SHA256
|
127
|
+
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
|
193
128
|
assert params['Signature']
|
194
|
-
|
195
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA384
|
196
|
-
|
197
|
-
query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
|
198
|
-
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
199
|
-
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
200
|
-
|
201
|
-
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
202
|
-
assert_equal signature_algorithm, OpenSSL::Digest::SHA384
|
203
|
-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
129
|
+
assert params['SigAlg'] == XMLSecurity::Document::SHA1
|
204
130
|
end
|
131
|
+
end
|
205
132
|
|
206
|
-
|
207
|
-
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512
|
208
|
-
|
209
|
-
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
|
210
|
-
assert params['SAMLResponse']
|
211
|
-
assert params[:RelayState]
|
212
|
-
assert params['Signature']
|
213
|
-
|
214
|
-
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA512
|
133
|
+
end
|
215
134
|
|
216
|
-
|
217
|
-
|
218
|
-
|
135
|
+
def decode_saml_response_payload(unauth_url)
|
136
|
+
payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
|
137
|
+
decoded = Base64.decode64(payload)
|
219
138
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
139
|
+
zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
140
|
+
inflated = zstream.inflate(decoded)
|
141
|
+
zstream.finish
|
142
|
+
zstream.close
|
143
|
+
inflated
|
225
144
|
end
|
145
|
+
|
226
146
|
end
|