ruby-saml 0.8.18 → 0.9

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 (90) hide show
  1. checksums.yaml +4 -4
  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 -93
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +36 -100
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -35
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +63 -373
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -122
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +25 -71
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +37 -102
  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 -155
  39. data/test/logoutresponse_test.rb +43 -32
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +102 -99
  42. data/test/response_test.rb +181 -495
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +7 -8
  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 +40 -50
  50. data/test/slo_logoutresponse_test.rb +86 -185
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +30 -81
  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>
@@ -3,7 +3,6 @@
3
3
  def default_response_opts
4
4
  {
5
5
  :uuid => "_28024690-000e-0130-b6d2-38f6b112be8b",
6
- :uuid2 => "_48024690-100e-1130-e6d2-28f6b112be71",
7
6
  :issue_instant => Time.now.strftime('%Y-%m-%dT%H:%M:%SZ'),
8
7
  :settings => settings
9
8
  }
@@ -14,11 +13,11 @@ def valid_response(opts = {})
14
13
 
15
14
  "<samlp:LogoutResponse
16
15
  xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
17
- ID=\"#{opts[:uuid]}\" Version=\"2.0\"
16
+ ID=\"#{random_id}\" Version=\"2.0\"
18
17
  IssueInstant=\"#{opts[:issue_instant]}\"
19
- Destination=\"#{opts[:settings].idp_slo_target_url}\"
20
- InResponseTo=\"#{opts[:uuid2]}\">
21
- <saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].idp_entity_id}</saml:Issuer>
18
+ Destination=\"#{opts[:settings].single_logout_service_url}\"
19
+ InResponseTo=\"#{opts[:uuid]}\">
20
+ <saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{opts[:settings].issuer}</saml:Issuer>
22
21
  <samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
23
22
  <samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
24
23
  Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\">
@@ -34,9 +33,9 @@ def unsuccessful_response(opts = {})
34
33
  xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
35
34
  ID=\"#{random_id}\" Version=\"2.0\"
36
35
  IssueInstant=\"#{opts[:issue_instant]}\"
37
- Destination=\"#{opts[:settings].idp_slo_target_url}\"
36
+ Destination=\"#{opts[:settings].single_logout_service_url}\"
38
37
  InResponseTo=\"#{opts[:uuid]}\">
39
- <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>
40
39
  <samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">
41
40
  <samlp:StatusCode xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\"
42
41
  Value=\"urn:oasis:names:tc:SAML:2.0:status:Requester\">
@@ -57,7 +56,7 @@ def settings
57
56
  {
58
57
  :assertion_consumer_service_url => "http://app.muda.no/sso/consume",
59
58
  :single_logout_service_url => "http://app.muda.no/sso/consume_logout",
60
- :sp_entity_id => "http://app.muda.no",
59
+ :issuer => "http://app.muda.no",
61
60
  :sp_name_qualifier => "http://sso.muda.no",
62
61
  :idp_sso_target_url => "http://sso.muda.no/sso",
63
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,71 +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
- end
12
- it "default to empty settings" do
13
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request)
14
- assert logoutrequest.settings.nil?
15
- end
16
- it "accept constructor-injected settings" do
17
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request, settings)
18
- assert !logoutrequest.settings.nil?
19
- end
20
- it "accept constructor-injected options" do
21
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request, nil, { :foo => :bar} )
22
- assert !logoutrequest.options.empty?
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?
23
15
  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
16
 
28
- assert_equal expected_request, logoutrequest.request
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
29
21
  end
30
- end
31
-
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
22
 
40
- assert_equal settings.idp_entity_id, logoutrequest.issuer
41
-
42
- assert_equal "testuser@example.com", logoutrequest.nameid
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?
27
+ end
43
28
 
44
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", logoutrequest.nameid_format
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?
45
33
  end
46
34
 
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! }
38
+ end
47
39
  end
48
40
 
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!
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
56
45
  end
46
+ end
57
47
 
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! }
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
62
52
  end
63
53
  end
64
54
 
65
- describe "#request_id" do
66
- it "extract the value of the Response ID" do
67
- logoutrequest = OneLogin::RubySaml::SloLogoutrequest.new(valid_request, settings)
68
- assert_equal "_28024690-000e-0130-b6d2-38f6b112be8b", logoutrequest.request_id
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
69
59
  end
70
60
  end
71
61