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.

Files changed (90) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -6
  4. data/Gemfile +2 -12
  5. data/README.md +363 -35
  6. data/Rakefile +14 -0
  7. data/changelog.md +22 -9
  8. data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
  9. data/lib/onelogin/ruby-saml/attributes.rb +26 -64
  10. data/lib/onelogin/ruby-saml/authrequest.rb +47 -89
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +34 -93
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -24
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +62 -322
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -121
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +26 -61
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -84
  20. data/lib/onelogin/ruby-saml/utils.rb +32 -199
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/ruby-saml.rb +5 -2
  23. data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
  24. data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
  25. data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
  26. data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
  27. data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
  28. data/lib/schemas/sstc-metadata-attr.xsd +35 -0
  29. data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
  30. data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
  31. data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
  32. data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
  33. data/lib/schemas/xml.xsd +287 -0
  34. data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
  35. data/lib/xml_security.rb +83 -235
  36. data/ruby-saml.gemspec +1 -0
  37. data/test/idp_metadata_parser_test.rb +54 -0
  38. data/test/logoutrequest_test.rb +68 -144
  39. data/test/logoutresponse_test.rb +43 -25
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +103 -90
  42. data/test/response_test.rb +181 -471
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +5 -5
  45. data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
  46. data/test/responses/response_with_multiple_attribute_values.xml +1 -1
  47. data/test/responses/slo_request.xml +4 -0
  48. data/test/settings_test.rb +25 -112
  49. data/test/slo_logoutrequest_test.rb +41 -44
  50. data/test/slo_logoutresponse_test.rb +87 -167
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +34 -84
  54. data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
  55. data/test/certificates/certificate.der +0 -0
  56. data/test/certificates/formatted_certificate +0 -14
  57. data/test/certificates/formatted_chained_certificate +0 -42
  58. data/test/certificates/formatted_private_key +0 -12
  59. data/test/certificates/formatted_rsa_private_key +0 -12
  60. data/test/certificates/invalid_certificate1 +0 -1
  61. data/test/certificates/invalid_certificate2 +0 -1
  62. data/test/certificates/invalid_certificate3 +0 -12
  63. data/test/certificates/invalid_chained_certificate1 +0 -1
  64. data/test/certificates/invalid_private_key1 +0 -1
  65. data/test/certificates/invalid_private_key2 +0 -1
  66. data/test/certificates/invalid_private_key3 +0 -10
  67. data/test/certificates/invalid_rsa_private_key1 +0 -1
  68. data/test/certificates/invalid_rsa_private_key2 +0 -1
  69. data/test/certificates/invalid_rsa_private_key3 +0 -10
  70. data/test/certificates/ruby-saml-2.crt +0 -15
  71. data/test/requests/logoutrequest_fixtures.rb +0 -47
  72. data/test/responses/encrypted_new_attack.xml.base64 +0 -1
  73. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  74. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  75. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  76. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  77. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  78. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  79. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  80. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  81. data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
  82. data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
  83. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  84. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  85. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  86. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  87. data/test/responses/response_wrapped.xml.base64 +0 -150
  88. data/test/responses/valid_response.xml.base64 +0 -1
  89. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  90. 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].idp_slo_target_url}\"
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].idp_entity_id}</saml:Issuer>
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].idp_slo_target_url}\"
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].idp_entity_id}</saml:Issuer>
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
- :sp_entity_id => "http://app.muda.no",
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>
@@ -64,4 +64,4 @@
64
64
  </saml:Attribute>
65
65
  </saml:AttributeStatement>
66
66
  </saml:Assertion>
67
- </samlp:Response>
67
+ </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>
@@ -1,18 +1,23 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
- class SettingsTest < Minitest::Test
3
+ class SettingsTest < Test::Unit::TestCase
4
4
 
5
- describe "Settings" do
6
- before do
5
+ context "Settings" do
6
+ setup do
7
7
  @settings = OneLogin::RubySaml::Settings.new
8
8
  end
9
- it "should provide getters and settings" do
9
+ should "should provide getters and settings" do
10
10
  accessors = [
11
- :assertion_consumer_service_url, :issuer, :sp_entity_id, :sp_name_qualifier,
12
- :idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format,
13
- :idp_slo_target_url, :name_identifier_value, :name_identifier_value_requested,
14
- :sessionindex, :assertion_consumer_logout_service_url,
15
- :passive, :force_authn, :protocol_binding, :single_logout_service_url, :single_logout_service_binding
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
- it "create settings from hash" do
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
- describe "#get_idp_cert" do
46
- it "returns nil when the cert is an empty string" do
47
- @settings.idp_cert = ""
48
- assert_nil @settings.get_idp_cert
49
- end
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
- it "get the fingerprint value when there are cert and fingerprint at the settings" do
144
- @settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
145
- @settings.idp_cert = ruby_saml_cert_text
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 File.expand_path(File.join(File.dirname(__FILE__), "requests/logoutrequest_fixtures"))
2
+ require 'responses/logoutresponse_fixtures'
3
3
 
4
- class SloLogoutrequestTest < Minitest::Test
4
+ class RubySamlTest < Test::Unit::TestCase
5
5
 
6
- describe "SloLogoutrequest" do
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
- describe "#new" do
9
- it "raise an exception when request is initialized with nil" do
10
- assert_raises(ArgumentError) { OneLogin::RubySaml::SloLogoutrequest.new(nil) }
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
- it "default to empty settings" do
13
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request)
14
- assert logoutrequest.settings.nil?
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
- it "accept constructor-injected settings" do
17
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request, settings)
18
- assert !logoutrequest.settings.nil?
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
- it "accept constructor-injected options" do
21
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request, nil, { :foo => :bar} )
22
- assert !logoutrequest.options.empty?
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
- assert_equal expected_request, logoutrequest.request
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
- describe "#validate" do
33
- it "validate the request" do
34
- in_relation_to_request_id = random_id
35
- settings.idp_entity_id = "https://example.com/idp"
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
- describe "#validate!" do
50
- it "validates good requests" do
51
- in_relation_to_request_id = random_id
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
- it "raise error for invalid xml" do
59
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(invalid_xml_request, settings)
60
-
61
- assert_raises(OneLogin::RubySaml::ValidationError) { logoutrequest.validate! }
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 < Minitest::Test
3
+ class SloLogoutresponseTest < Test::Unit::TestCase
4
4
 
5
- describe "SloLogoutresponse" do
5
+ context "SloLogoutresponse" do
6
+ settings = OneLogin::RubySaml::Settings.new
6
7
 
7
- let(:settings) { OneLogin::RubySaml::Settings.new }
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
- it "create the deflated SAMLResponse URL parameter" do
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
- inflated = decode_saml_response_payload(unauth_url)
22
- assert_match /^<samlp:LogoutResponse/, inflated
23
- end
15
+ assert request.is_valid?
24
16
 
25
- it "support additional params" do
26
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :hello => nil })
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
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :foo => "bar" })
30
- assert_match /&foo=bar$/, unauth_url
20
+ inflated = decode_saml_response_payload(unauth_url)
31
21
 
32
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => "http://idp.example.com" })
33
- assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
22
+ assert_match /^<samlp:LogoutResponse/, inflated
34
23
  end
35
24
 
36
- it "RelayState cases" do
37
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => nil })
38
- assert !unauth_url.include?('RelayState')
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, nil, nil, { :RelayState => "http://example.com" })
41
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
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, nil, nil, { 'RelayState' => nil })
44
- assert !unauth_url.include?('RelayState')
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, nil, nil, { 'RelayState' => "http://example.com" })
47
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
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
- it "set InResponseTo to the ID from the logout request" do
51
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, '_c0348950-935b-0131-1060-782bcb56fcaa')
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
- it "set a custom successful logout message on the response" do
58
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message")
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
- describe "when the settings indicate to sign (embedded) logout response" do
65
-
66
- before do
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
- end
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
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
87
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
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
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/, response_xml
112
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/, response_xml
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
- it "create a signed logout response with 256 digest and signature methods" do
116
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
117
- settings.security[:digest_method] = XMLSecurity::Document::SHA256
118
-
119
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
120
-
121
- response_xml = Base64.decode64(params["SAMLResponse"])
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
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
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
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha384'\/>/, response_xml
136
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha512'\/>/, response_xml
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
- describe "#create_params when the settings indicate to sign the logout response" do
141
-
142
- let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
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
- end
149
-
150
- it "create a signature parameter with RSA_SHA1 and validate it" do
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
- it "create a signature parameter with RSA_SHA256 /SHA256 and validate it" do
169
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
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
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
177
-
178
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
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
- it "create a signature parameter with RSA_SHA512 / SHA512 and validate it" do
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
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
217
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
218
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
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
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
221
- assert_equal signature_algorithm, OpenSSL::Digest::SHA512
222
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
223
- end
224
- end
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