ruby-saml 1.9.0 → 1.12.0

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 (157) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +30 -14
  3. data/README.md +108 -22
  4. data/changelog.md +38 -0
  5. data/lib/onelogin/ruby-saml/attributes.rb +24 -1
  6. data/lib/onelogin/ruby-saml/authrequest.rb +23 -6
  7. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +239 -171
  8. data/lib/onelogin/ruby-saml/logging.rb +3 -3
  9. data/lib/onelogin/ruby-saml/logoutrequest.rb +20 -5
  10. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -9
  11. data/lib/onelogin/ruby-saml/metadata.rb +11 -3
  12. data/lib/onelogin/ruby-saml/response.rb +67 -21
  13. data/lib/onelogin/ruby-saml/saml_message.rb +12 -2
  14. data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
  15. data/lib/onelogin/ruby-saml/settings.rb +73 -7
  16. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +20 -1
  17. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +38 -16
  18. data/lib/onelogin/ruby-saml/utils.rb +74 -1
  19. data/lib/onelogin/ruby-saml/version.rb +1 -1
  20. data/lib/xml_security.rb +34 -6
  21. data/ruby-saml.gemspec +15 -7
  22. metadata +36 -278
  23. data/test/certificates/certificate1 +0 -12
  24. data/test/certificates/certificate_without_head_foot +0 -1
  25. data/test/certificates/formatted_certificate +0 -14
  26. data/test/certificates/formatted_chained_certificate +0 -42
  27. data/test/certificates/formatted_private_key +0 -12
  28. data/test/certificates/formatted_rsa_private_key +0 -12
  29. data/test/certificates/invalid_certificate1 +0 -1
  30. data/test/certificates/invalid_certificate2 +0 -1
  31. data/test/certificates/invalid_certificate3 +0 -12
  32. data/test/certificates/invalid_chained_certificate1 +0 -1
  33. data/test/certificates/invalid_private_key1 +0 -1
  34. data/test/certificates/invalid_private_key2 +0 -1
  35. data/test/certificates/invalid_private_key3 +0 -10
  36. data/test/certificates/invalid_rsa_private_key1 +0 -1
  37. data/test/certificates/invalid_rsa_private_key2 +0 -1
  38. data/test/certificates/invalid_rsa_private_key3 +0 -10
  39. data/test/certificates/ruby-saml-2.crt +0 -15
  40. data/test/certificates/ruby-saml.crt +0 -14
  41. data/test/certificates/ruby-saml.key +0 -15
  42. data/test/idp_metadata_parser_test.rb +0 -579
  43. data/test/logging_test.rb +0 -62
  44. data/test/logout_requests/invalid_slo_request.xml +0 -6
  45. data/test/logout_requests/slo_request.xml +0 -4
  46. data/test/logout_requests/slo_request.xml.base64 +0 -1
  47. data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
  48. data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
  49. data/test/logout_requests/slo_request_with_session_index.xml +0 -5
  50. data/test/logout_responses/logoutresponse_fixtures.rb +0 -67
  51. data/test/logoutrequest_test.rb +0 -226
  52. data/test/logoutresponse_test.rb +0 -402
  53. data/test/metadata/idp_descriptor.xml +0 -26
  54. data/test/metadata/idp_descriptor_2.xml +0 -56
  55. data/test/metadata/idp_descriptor_3.xml +0 -14
  56. data/test/metadata/idp_descriptor_4.xml +0 -72
  57. data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
  58. data/test/metadata/idp_metadata_multi_certs.xml +0 -75
  59. data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
  60. data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
  61. data/test/metadata/idp_multiple_descriptors.xml +0 -53
  62. data/test/metadata/no_idp_descriptor.xml +0 -21
  63. data/test/metadata_test.rb +0 -331
  64. data/test/request_test.rb +0 -323
  65. data/test/response_test.rb +0 -1619
  66. data/test/responses/adfs_response_sha1.xml +0 -46
  67. data/test/responses/adfs_response_sha256.xml +0 -46
  68. data/test/responses/adfs_response_sha384.xml +0 -46
  69. data/test/responses/adfs_response_sha512.xml +0 -46
  70. data/test/responses/adfs_response_xmlns.xml +0 -45
  71. data/test/responses/attackxee.xml +0 -13
  72. data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
  73. data/test/responses/invalids/empty_destination.xml.base64 +0 -1
  74. data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
  75. data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
  76. data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
  77. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  78. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  79. data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
  80. data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
  81. data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
  82. data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
  83. data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
  84. data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
  85. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  86. data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
  87. data/test/responses/invalids/no_conditions.xml.base64 +0 -1
  88. data/test/responses/invalids/no_id.xml.base64 +0 -1
  89. data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
  90. data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
  91. data/test/responses/invalids/no_nameid.xml.base64 +0 -1
  92. data/test/responses/invalids/no_saml2.xml.base64 +0 -1
  93. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  94. data/test/responses/invalids/no_status.xml.base64 +0 -1
  95. data/test/responses/invalids/no_status_code.xml.base64 +0 -1
  96. data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
  97. data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
  98. data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
  99. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  100. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  101. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  102. data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
  103. data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
  104. data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
  105. data/test/responses/no_signature_ns.xml +0 -48
  106. data/test/responses/open_saml_response.xml +0 -56
  107. data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
  108. data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
  109. data/test/responses/response_double_status_code.xml.base64 +0 -1
  110. data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
  111. data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
  112. data/test/responses/response_eval.xml +0 -7
  113. data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
  114. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  115. data/test/responses/response_node_text_attack2.xml.base64 +0 -1
  116. data/test/responses/response_node_text_attack3.xml.base64 +0 -1
  117. data/test/responses/response_unsigned_xml_base64 +0 -1
  118. data/test/responses/response_with_ampersands.xml +0 -139
  119. data/test/responses/response_with_ampersands.xml.base64 +0 -93
  120. data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
  121. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  122. data/test/responses/response_with_multiple_attribute_values.xml +0 -67
  123. data/test/responses/response_with_retrieval_method.xml +0 -26
  124. data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
  125. data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
  126. data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
  127. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  128. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  129. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  130. data/test/responses/response_without_attributes.xml.base64 +0 -79
  131. data/test/responses/response_without_reference_uri.xml.base64 +0 -1
  132. data/test/responses/response_wrapped.xml.base64 +0 -150
  133. data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
  134. data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  135. data/test/responses/signed_nameid_in_atts.xml +0 -47
  136. data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
  137. data/test/responses/simple_saml_php.xml +0 -71
  138. data/test/responses/starfield_response.xml.base64 +0 -1
  139. data/test/responses/test_sign.xml +0 -43
  140. data/test/responses/unsigned_encrypted_adfs.xml +0 -23
  141. data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
  142. data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
  143. data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
  144. data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
  145. data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
  146. data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
  147. data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  148. data/test/responses/valid_response.xml.base64 +0 -1
  149. data/test/responses/valid_response_with_formatted_x509certificate.xml.base64 +0 -1
  150. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  151. data/test/saml_message_test.rb +0 -56
  152. data/test/settings_test.rb +0 -329
  153. data/test/slo_logoutrequest_test.rb +0 -448
  154. data/test/slo_logoutresponse_test.rb +0 -199
  155. data/test/test_helper.rb +0 -327
  156. data/test/utils_test.rb +0 -254
  157. data/test/xml_security_test.rb +0 -421
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d36c7827c8bb0a1ab808a352ecb85bb925aca401
4
- data.tar.gz: e823dc21a31d81901cad0bdcdc2c5f737ed37d42
2
+ SHA256:
3
+ metadata.gz: 43bc92cf8a14835577d9bb32d1bdcef71fd5ffccb351dd41ac9b56863fb173c7
4
+ data.tar.gz: e7975fcf413d9c64801f7b5190246685548205034dc74315bc169738697e1006
5
5
  SHA512:
6
- metadata.gz: d2a444bfe39a2236b37ff979015dd1b7e82f06d06f23abf38251bebdc33b64ca91b76c128811a7636335b00bfa1609ef0a7a450ff99be8613ea6f0d4f2aea22d
7
- data.tar.gz: 974a863b07f77aaef63393a23d825a1af3bfd3acc4e5d8ad00902d5efd556cf7d2062dac80e44f06c5a5cbe42154ffe2632351d897f18bcc7210fa0582b24d7e
6
+ metadata.gz: 0a09fcb8777969eb6d54b29d20520c7e17e3f7dc128cfc81475eba8c9b31f5926f2b64d308b18268762b43fb60cf7956f6e266c1f5343d2b9d58e545be0c3392
7
+ data.tar.gz: 8e9008647a610935764b2f578b76c5eb72d09be482d76b5f4d8ab51fd29d4569a3ba2e2db61f63fbdde27bd1be14bf4afdeffe1c7f699afc0b7d5e1c85d0fe09
data/.travis.yml CHANGED
@@ -1,32 +1,48 @@
1
- sudo: false
2
1
  language: ruby
3
2
  rvm:
4
- - 1.8.7
5
3
  - 1.9.3
6
4
  - 2.0.0
7
- - 2.1.5
8
- - 2.2.0
9
- - 2.3.0
10
- - 2.4.0
11
- - 2.5.0
12
- - ree
5
+ - 2.1.10
6
+ - 2.2.10
7
+ - 2.3.8
8
+ - 2.4.6
9
+ - 2.5.8
10
+ - 2.6.6
11
+ - 2.7.2
12
+ - 3.0.0
13
13
  - jruby-1.7.27
14
14
  - jruby-9.1.17.0
15
- - jruby-9.2.0.0
15
+ - jruby-9.2.13.0
16
16
  gemfile:
17
17
  - Gemfile
18
18
  - gemfiles/nokogiri-1.5.gemfile
19
+ before_install:
20
+ - gem update bundler
19
21
  matrix:
20
22
  exclude:
21
- - rvm: 1.8.7
22
- gemfile: Gemfile
23
- - rvm: ree
24
- gemfile: Gemfile
25
23
  - rvm: jruby-1.7.27
26
24
  gemfile: gemfiles/nokogiri-1.5.gemfile
27
25
  - rvm: jruby-9.1.17.0
28
26
  gemfile: gemfiles/nokogiri-1.5.gemfile
29
- - rvm: jruby-9.2.0.0
27
+ - rvm: jruby-9.2.13.0
28
+ gemfile: gemfiles/nokogiri-1.5.gemfile
29
+ - rvm: 2.1.5
30
+ gemfile: gemfiles/nokogiri-1.5.gemfile
31
+ - rvm: 2.1.10
32
+ gemfile: gemfiles/nokogiri-1.5.gemfile
33
+ - rvm: 2.2.10
34
+ gemfile: gemfiles/nokogiri-1.5.gemfile
35
+ - rvm: 2.3.8
36
+ gemfile: gemfiles/nokogiri-1.5.gemfile
37
+ - rvm: 2.4.6
38
+ gemfile: gemfiles/nokogiri-1.5.gemfile
39
+ - rvm: 2.5.8
40
+ gemfile: gemfiles/nokogiri-1.5.gemfile
41
+ - rvm: 2.6.6
42
+ gemfile: gemfiles/nokogiri-1.5.gemfile
43
+ - rvm: 2.7.2
44
+ gemfile: gemfiles/nokogiri-1.5.gemfile
45
+ - rvm: 3.0.0
30
46
  gemfile: gemfiles/nokogiri-1.5.gemfile
31
47
  env:
32
48
  - JRUBY_OPTS="--debug"
data/README.md CHANGED
@@ -1,4 +1,22 @@
1
- # Ruby SAML [![Build Status](https://secure.travis-ci.org/onelogin/ruby-saml.svg)](http://travis-ci.org/onelogin/ruby-saml) [![Coverage Status](https://coveralls.io/repos/onelogin/ruby-saml/badge.svg?branch=master%0A)](https://coveralls.io/r/onelogin/ruby-saml?branch=master%0A) [![Gem Version](https://badge.fury.io/rb/ruby-saml.svg)](http://badge.fury.io/rb/ruby-saml)
1
+ # Ruby SAML [![Build Status](https://secure.travis-ci.org/onelogin/ruby-saml.svg)](http://travis-ci.org/onelogin/ruby-saml) [![Coverage Status](https://coveralls.io/repos/onelogin/ruby-saml/badge.svg?branch=master)](https://coveralls.io/r/onelogin/ruby-saml?branch=master)
2
+
3
+ ## Updating from 1.11.x to 1.12.0
4
+ Version `1.12.0` adds support for gcm algorithm and
5
+ change/adds specific error messages for signature validations
6
+
7
+ ## Updating from 1.10.x to 1.11.0
8
+ Version `1.11.0` deprecates the use of `settings.issuer` in favour of `settings.sp_entity_id`.
9
+ There are two new security settings: `settings.security[:check_idp_cert_expiration]` and `settings.security[:check_sp_cert_expiration]` (both false by default) that check if the IdP or SP X.509 certificate has expired, respectively.
10
+
11
+ Version `1.10.2` includes the `valid_until` attribute in parsed IdP metadata.
12
+
13
+ Version `1.10.1` improves Ruby 1.8.7 support.
14
+
15
+ ## Updating from 1.9.0 to 1.10.0
16
+ Version `1.10.0` improves IdpMetadataParser to allow parse multiple IDPSSODescriptor, Add Subject support on AuthNRequest to allow SPs provide info to the IdP about the user to be authenticated and updates the format_cert method to accept certs with /\x0d/
17
+
18
+ ## Updating from 1.8.0 to 1.9.0
19
+ Version `1.9.0` better supports Ruby 2.4+ and JRuby 9.2.0.0. `Settings` initialization now has a second parameter, `keep_security_settings` (default: false), which saves security settings attributes that are not explicitly overridden, if set to true.
2
20
 
3
21
  ## Updating from 1.7.X to 1.8.0
4
22
  On Version `1.8.0`, creating AuthRequests/LogoutRequests/LogoutResponses with nil RelayState param will not generate a URL with an empty RelayState parameter anymore. It also changes the invalid audience error message.
@@ -99,8 +117,12 @@ We created a demo project for Rails4 that uses the latest version of this librar
99
117
  * 2.2.x
100
118
  * 2.3.x
101
119
  * 2.4.x
120
+ * 2.5.x
121
+ * 2.6.x
122
+ * 2.7.x
102
123
  * JRuby 1.7.19
103
124
  * JRuby 9.0.0.0
125
+ * JRuby 9.2.0.0
104
126
 
105
127
  ## Adding Features, Pull Requests
106
128
  * Fork the repository
@@ -114,6 +136,17 @@ We created a demo project for Rails4 that uses the latest version of this librar
114
136
 
115
137
  If you believe you have discovered a security vulnerability in this gem, please report it at https://www.onelogin.com/security with a description. We follow responsible disclosure guidelines, and will work with you to quickly find a resolution.
116
138
 
139
+ ### Security warning
140
+
141
+ Some tools may incorrectly report ruby-saml is a potential security vulnerability.
142
+ ruby-saml depends on Nokogiri, and it's possible to use Nokogiri in a dangerous way
143
+ (by enabling its DTDLOAD option and disabling its NONET option).
144
+ This dangerous Nokogiri configuration, which is sometimes used by other components,
145
+ can create an XML External Entity (XXE) vulnerability if the XML data is not trusted.
146
+ However, ruby-saml never enables this dangerous Nokogiri configuration;
147
+ ruby-saml never enables DTDLOAD, and it never disables NONET.
148
+
149
+
117
150
  ## Getting Started
118
151
  In order to use the toolkit you will need to install the gem (either manually or using Bundler), and require the library in your Ruby application:
119
152
 
@@ -121,7 +154,7 @@ Using `Gemfile`
121
154
 
122
155
  ```ruby
123
156
  # latest stable
124
- gem 'ruby-saml', '~> 1.8.0'
157
+ gem 'ruby-saml', '~> 1.11.0'
125
158
 
126
159
  # or track master for bleeding-edge
127
160
  gem 'ruby-saml', :github => 'onelogin/ruby-saml'
@@ -170,7 +203,7 @@ To override the default behavior and control the destination of log messages, pr
170
203
  a ruby Logger object to the gem's logging singleton:
171
204
 
172
205
  ```ruby
173
- OneLogin::RubySaml::Logging.logger = Logger.new(File.open('/var/log/ruby-saml.log', 'w'))
206
+ OneLogin::RubySaml::Logging.logger = Logger.new('/var/log/ruby-saml.log')
174
207
  ```
175
208
 
176
209
  ## The Initialization Phase
@@ -184,6 +217,17 @@ def init
184
217
  end
185
218
  ```
186
219
 
220
+ If the SP knows who should be authenticated in the IdP, then can provide that info as follows:
221
+
222
+ ```ruby
223
+ def init
224
+ request = OneLogin::RubySaml::Authrequest.new
225
+ saml_settings.name_identifier_value_requested = "testuser@example.com"
226
+ saml_settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
227
+ redirect_to(request.create(saml_settings))
228
+ end
229
+ ```
230
+
187
231
  Once you've redirected back to the identity provider, it will ensure that the user has been authorized and redirect back to your application for final consumption. This can look something like this (the `authorize_success` and `authorize_failure` methods are specific to your application):
188
232
 
189
233
  ```ruby
@@ -197,6 +241,7 @@ def consume
197
241
  session[:attributes] = response.attributes
198
242
  else
199
243
  authorize_failure # This method shows an error message
244
+ # List of errors is available in response.errors array
200
245
  end
201
246
  end
202
247
  ```
@@ -218,10 +263,10 @@ def saml_settings
218
263
  settings = OneLogin::RubySaml::Settings.new
219
264
 
220
265
  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
221
- settings.issuer = "http://#{request.host}/saml/metadata"
266
+ settings.sp_entity_id = "http://#{request.host}/saml/metadata"
222
267
  settings.idp_entity_id = "https://app.onelogin.com/saml/metadata/#{OneLoginAppId}"
223
- settings.idp_sso_target_url = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
224
- settings.idp_slo_target_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}"
268
+ settings.idp_sso_service_url = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
269
+ settings.idp_slo_service_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}"
225
270
  settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint
226
271
  settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
227
272
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
@@ -242,6 +287,8 @@ def saml_settings
242
287
  end
243
288
  ```
244
289
 
290
+ The use of settings.issuer is deprecated in favour of settings.sp_entity_id since version 1.11.0
291
+
245
292
  Some assertion validations can be skipped by passing parameters to `OneLogin::RubySaml::Response.new()`. For example, you can skip the `AuthnStatement`, `Conditions`, `Recipient`, or the `SubjectConfirmation` validations by initializing the response with different options:
246
293
 
247
294
  ```ruby
@@ -249,6 +296,7 @@ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_authnst
249
296
  response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_conditions: true}) # skips conditions
250
297
  response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_subject_confirmation: true}) # skips subject confirmation
251
298
  response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_recipient_check: true}) # doens't skip subject confirmation, but skips the recipient check which is a sub check of the subject_confirmation check
299
+ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_audience: true}) # skips audience check
252
300
  ```
253
301
 
254
302
  All that's left is to wrap everything in a controller and reference it in the initialization and consumption URLs in OneLogin. A full controller example could look like this:
@@ -272,6 +320,7 @@ class SamlController < ApplicationController
272
320
  session[:attributes] = response.attributes
273
321
  else
274
322
  authorize_failure # This method shows an error message
323
+ # List of errors is available in response.errors array
275
324
  end
276
325
  end
277
326
 
@@ -281,8 +330,8 @@ class SamlController < ApplicationController
281
330
  settings = OneLogin::RubySaml::Settings.new
282
331
 
283
332
  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
284
- settings.issuer = "http://#{request.host}/saml/metadata"
285
- settings.idp_sso_target_url = "https://app.onelogin.com/saml/signon/#{OneLoginAppId}"
333
+ settings.sp_entity_id = "http://#{request.host}/saml/metadata"
334
+ settings.idp_sso_service_url = "https://app.onelogin.com/saml/signon/#{OneLoginAppId}"
286
335
  settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint
287
336
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
288
337
 
@@ -344,7 +393,7 @@ def saml_settings
344
393
  settings = idp_metadata_parser.parse_remote("https://example.com/auth/saml2/idp/metadata")
345
394
 
346
395
  settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
347
- settings.issuer = "http://#{request.host}/saml/metadata"
396
+ settings.sp_entity_id = "http://#{request.host}/saml/metadata"
348
397
  settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
349
398
  # Optional for most SAML IdPs
350
399
  settings.authn_context = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
@@ -355,11 +404,11 @@ end
355
404
  The following attributes are set:
356
405
  * idp_entity_id
357
406
  * name_identifier_format
358
- * idp_sso_target_url
359
- * idp_slo_target_url
407
+ * idp_sso_service_url
408
+ * idp_slo_service_url
360
409
  * idp_attribute_names
361
- * idp_cert
362
- * idp_cert_fingerprint
410
+ * idp_cert
411
+ * idp_cert_fingerprint
363
412
  * idp_cert_multi
364
413
 
365
414
  ### Retrieve one Entity Descriptor when many exist in Metadata
@@ -422,6 +471,9 @@ Imagine this `saml:AttributeStatement`
422
471
  <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
423
472
  <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1"/>
424
473
  </saml:Attribute>
474
+ <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
475
+ <saml:AttributeValue>usersName</saml:AttributeValue>
476
+ </saml:Attribute>
425
477
  </saml:AttributeStatement>
426
478
  ```
427
479
 
@@ -432,7 +484,8 @@ pp(response.attributes) # is an OneLogin::RubySaml::Attributes object
432
484
  "another_value"=>["value1", "value2"],
433
485
  "role"=>["role1", "role2", "role3"],
434
486
  "attribute_with_nil_value"=>[nil],
435
- "attribute_with_nils_and_empty_strings"=>["", "valuePresent", nil, nil]}>
487
+ "attribute_with_nils_and_empty_strings"=>["", "valuePresent", nil, nil]
488
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"=>["usersName"]}>
436
489
 
437
490
  # Active single_value_compatibility
438
491
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
@@ -449,6 +502,9 @@ pp(response.attributes.single(:role))
449
502
  pp(response.attributes.multi(:role))
450
503
  # => ["role1", "role2", "role3"]
451
504
 
505
+ pp(response.attributes.fetch(:role))
506
+ # => "role1"
507
+
452
508
  pp(response.attributes[:attribute_with_nil_value])
453
509
  # => nil
454
510
 
@@ -464,6 +520,9 @@ pp(response.attributes.single(:not_exists))
464
520
  pp(response.attributes.multi(:not_exists))
465
521
  # => nil
466
522
 
523
+ pp(response.attributes.fetch(/givenname/))
524
+ # => "usersName"
525
+
467
526
  # Deactive single_value_compatibility
468
527
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
469
528
 
@@ -479,6 +538,9 @@ pp(response.attributes.single(:role))
479
538
  pp(response.attributes.multi(:role))
480
539
  # => ["role1", "role2", "role3"]
481
540
 
541
+ pp(response.attributes.fetch(:role))
542
+ # => ["role1", "role2", "role3"]
543
+
482
544
  pp(response.attributes[:attribute_with_nil_value])
483
545
  # => [nil]
484
546
 
@@ -493,11 +555,17 @@ pp(response.attributes.single(:not_exists))
493
555
 
494
556
  pp(response.attributes.multi(:not_exists))
495
557
  # => nil
558
+
559
+ pp(response.attributes.fetch(/givenname/))
560
+ # => ["usersName"]
496
561
  ```
497
562
 
498
563
  The `saml:AuthnContextClassRef` of the AuthNRequest can be provided by `settings.authn_context`; possible values are described at [SAMLAuthnCxt]. The comparison method can be set using `settings.authn_context_comparison` parameter. Possible values include: 'exact', 'better', 'maximum' and 'minimum' (default value is 'exact').
499
564
  To add a `saml:AuthnContextDeclRef`, define `settings.authn_context_decl_ref`.
500
565
 
566
+ In a SP-initiated flow, the SP can indicate to the IdP the subject that should be authenticated. This is done by defining the `settings.name_identifier_value_requested` before
567
+ building the authrequest object.
568
+
501
569
 
502
570
  ## Signing
503
571
 
@@ -525,6 +593,8 @@ The settings related to sign are stored in the `security` attribute of the setti
525
593
  # Embeded signature or HTTP GET parameter signature
526
594
  # Note that metadata signature is always embedded regardless of this value.
527
595
  settings.security[:embed_sign] = false
596
+ settings.security[:check_idp_cert_expiration] = false # Enable or not IdP x509 cert expiration check
597
+ settings.security[:check_sp_cert_expiration] = false # Enable or not SP x509 cert expiration check
528
598
  ```
529
599
 
530
600
  Notice that the RelayState parameter is used when creating the Signature on the HTTP-Redirect Binding.
@@ -532,7 +602,7 @@ Remember to provide it to the Signature builder if you are sending a `GET RelayS
532
602
  signature validation process will fail at the Identity Provider.
533
603
 
534
604
  The Service Provider will sign the request/responses with its private key.
535
- The Identity Provider will validate the sign of the received request/responses with the public x500 cert of the
605
+ The Identity Provider will validate the sign of the received request/responses with the public x509 cert of the
536
606
  Service Provider.
537
607
 
538
608
  Notice that this toolkit uses 'settings.certificate' and 'settings.private_key' for the sign and decrypt processes.
@@ -573,21 +643,27 @@ def sp_logout_request
573
643
  # LogoutRequest accepts plain browser requests w/o paramters
574
644
  settings = saml_settings
575
645
 
576
- if settings.idp_slo_target_url.nil?
646
+ if settings.idp_slo_service_url.nil?
577
647
  logger.info "SLO IdP Endpoint not found in settings, executing then a normal logout'"
578
648
  delete_session
579
649
  else
580
650
 
581
- # Since we created a new SAML request, save the transaction_id
582
- # to compare it with the response we get back
583
651
  logout_request = OneLogin::RubySaml::Logoutrequest.new()
584
- session[:transaction_id] = logout_request.uuid
585
- logger.info "New SP SLO for userid '#{session[:userid]}' transactionid '#{session[:transaction_id]}'"
652
+ logger.info "New SP SLO for userid '#{session[:userid]}' transactionid '#{logout_request.uuid}'"
586
653
 
587
654
  if settings.name_identifier_value.nil?
588
655
  settings.name_identifier_value = session[:userid]
589
656
  end
590
657
 
658
+ # Ensure user is logged out before redirect to IdP, in case anything goes wrong during single logout process (as recommended by saml2int [SDP-SP34])
659
+ logged_user = session[:userid]
660
+ logger.info "Delete session for '#{session[:userid]}'"
661
+ delete_session
662
+
663
+ # Save the transaction_id to compare it with the response we get back
664
+ session[:transaction_id] = logout_request.uuid
665
+ session[:logged_out_user] = logged_user
666
+
591
667
  relayState = url_for controller: 'saml', action: 'index'
592
668
  redirect_to(logout_request.create(settings, :RelayState => relayState))
593
669
  end
@@ -615,7 +691,7 @@ def process_logout_response
615
691
  logger.error "The SAML Logout Response is invalid"
616
692
  else
617
693
  # Actually log out this session
618
- logger.info "Delete session for '#{session[:userid]}'"
694
+ logger.info "SLO completed for '#{session[:logged_out_user]}'"
619
695
  delete_session
620
696
  end
621
697
  end
@@ -624,6 +700,8 @@ end
624
700
  def delete_session
625
701
  session[:userid] = nil
626
702
  session[:attributes] = nil
703
+ session[:transaction_id] = nil
704
+ session[:logged_out_user] = nil
627
705
  end
628
706
  ```
629
707
 
@@ -636,7 +714,7 @@ def idp_logout_request
636
714
  logout_request = OneLogin::RubySaml::SloLogoutrequest.new(params[:SAMLRequest])
637
715
  if !logout_request.is_valid?
638
716
  logger.error "IdP initiated LogoutRequest was not valid!"
639
- render :inline => logger.error
717
+ return render :inline => logger.error
640
718
  end
641
719
  logger.info "IdP initiated Logout for #{logout_request.name_id}"
642
720
 
@@ -691,6 +769,14 @@ class SamlController < ApplicationController
691
769
  end
692
770
  ```
693
771
 
772
+ You can add ValidUntil and CacheDuration to the XML Metadata using instead
773
+ ```ruby
774
+ # Valid until => 2 days from now
775
+ # Cache duration = 604800s = 1 week
776
+ valid_until = Time.now + 172800
777
+ cache_duration = 604800
778
+ meta.generate(settings, false, valid_until, cache_duration)
779
+ ```
694
780
 
695
781
  ## Clock Drift
696
782
 
data/changelog.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # RubySaml Changelog
2
2
 
3
+ ### 1.12.0 (Feb 18, 2021)
4
+ * Support AES-128-GCM, AES-192-GCM, and AES-256-GCM encryptions
5
+ * Parse & return SLO ResponseLocation in IDPMetadataParser & Settings
6
+ * Adding idp_sso_service_url and idp_slo_service_url settings
7
+ * [#536](https://github.com/onelogin/ruby-saml/pull/536) Adding feth method to be able retrieve attributes based on regex
8
+ * Reduce size of built gem by excluding the test folder
9
+ * Improve protection on Zlib deflate decompression bomb attack.
10
+ * Add ValidUntil and cacheDuration support on Metadata generator
11
+ * Add support for cacheDuration at the IdpMetadataParser
12
+ * Support customizable statusCode on generated LogoutResponse
13
+ * [#545](https://github.com/onelogin/ruby-saml/pull/545) More specific error messages for signature validation
14
+ * Support Process Transform
15
+ * Raise SettingError if invoking an action with no endpoint defined on the settings
16
+ * Made IdpMetadataParser more extensible for subclasses
17
+ *[#548](https://github.com/onelogin/ruby-saml/pull/548) Add :skip_audience option
18
+ * [#555](https://github.com/onelogin/ruby-saml/pull/555) Define 'soft' variable to prevent exception when doc cert is invalid
19
+ * Improve documentation
20
+
21
+ ### 1.11.0 (Jul 24, 2019)
22
+
23
+ * Deprecate settings.issuer in favor of settings.sp_entity_id
24
+ * Add support for certification expiration
25
+
26
+ ### 1.10.2 (Apr 29, 2019)
27
+
28
+ * Add valid until, accessor
29
+ * Fix Rubygem metadata that requested nokogiri <= 1.5.11
30
+
31
+ ### 1.10.1 (Apr 08, 2019)
32
+
33
+ * Fix ruby 1.8.7 incompatibilities
34
+
35
+ ### 1.10.0 (Mar 21, 2019)
36
+ * Add Subject support on AuthNRequest to allow SPs provide info to the IdP about the user to be authenticated
37
+ * Improves IdpMetadataParser to allow parse multiple IDPSSODescriptors
38
+ * Improves format_cert method to accept certs with /\x0d/
39
+ * Forces nokogiri >= 1.8.2 when possible
40
+
3
41
  ### 1.9.0 (Sept 03, 2018)
4
42
  * [#458](https://github.com/onelogin/ruby-saml/pull/458) Remove ruby 2.4+ warnings
5
43
  * Improve JRuby support
@@ -79,7 +79,7 @@ module OneLogin
79
79
  self.class.single_value_compatibility ? single(canonize_name(name)) : multi(canonize_name(name))
80
80
  end
81
81
 
82
- # @return [Array] Return all attributes as an array
82
+ # @return [Hash] Return all attributes as a hash
83
83
  #
84
84
  def all
85
85
  attributes
@@ -113,6 +113,29 @@ module OneLogin
113
113
  end
114
114
  end
115
115
 
116
+ # Fetch attribute value using name or regex
117
+ # @param name [String|Regexp] The attribute name
118
+ # @return [String|Array] Depending on the single value compatibility status this returns:
119
+ # - First value if single_value_compatibility = true
120
+ # response.attributes['mail'] # => 'user@example.com'
121
+ # - All values if single_value_compatibility = false
122
+ # response.attributes['mail'] # => ['user@example.com','user@example.net']
123
+ #
124
+ def fetch(name)
125
+ attributes.each_key do |attribute_key|
126
+ if name.is_a?(Regexp)
127
+ if name.method_exists? :match?
128
+ return self[attribute_key] if name.match?(attribute_key)
129
+ else
130
+ return self[attribute_key] if name.match(attribute_key)
131
+ end
132
+ elsif canonize_name(name) == canonize_name(attribute_key)
133
+ return self[attribute_key]
134
+ end
135
+ end
136
+ nil
137
+ end
138
+
116
139
  protected
117
140
 
118
141
  # stringifies all names so both 'email' and :email return the same result