ruby-saml 1.10.1 → 1.12.2
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.
Potentially problematic release.
This version of ruby-saml might be problematic. Click here for more details.
- checksums.yaml +7 -7
- data/.travis.yml +21 -20
- data/README.md +95 -26
- data/changelog.md +40 -0
- data/lib/onelogin/ruby-saml/attributes.rb +24 -1
- data/lib/onelogin/ruby-saml/authrequest.rb +11 -6
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +70 -24
- data/lib/onelogin/ruby-saml/logging.rb +3 -3
- data/lib/onelogin/ruby-saml/logoutrequest.rb +11 -5
- data/lib/onelogin/ruby-saml/logoutresponse.rb +21 -2
- data/lib/onelogin/ruby-saml/metadata.rb +11 -3
- data/lib/onelogin/ruby-saml/response.rb +64 -23
- data/lib/onelogin/ruby-saml/saml_message.rb +6 -0
- data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
- data/lib/onelogin/ruby-saml/settings.rb +72 -7
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +20 -1
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +31 -17
- data/lib/onelogin/ruby-saml/utils.rb +69 -0
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +34 -6
- data/ruby-saml.gemspec +9 -5
- metadata +161 -383
- data/test/certificates/certificate.der +0 -0
- data/test/certificates/certificate1 +0 -12
- data/test/certificates/certificate_without_head_foot +0 -1
- data/test/certificates/formatted_certificate +0 -14
- data/test/certificates/formatted_chained_certificate +0 -42
- data/test/certificates/formatted_private_key +0 -12
- data/test/certificates/formatted_rsa_private_key +0 -12
- data/test/certificates/invalid_certificate1 +0 -1
- data/test/certificates/invalid_certificate2 +0 -1
- data/test/certificates/invalid_certificate3 +0 -12
- data/test/certificates/invalid_chained_certificate1 +0 -1
- data/test/certificates/invalid_private_key1 +0 -1
- data/test/certificates/invalid_private_key2 +0 -1
- data/test/certificates/invalid_private_key3 +0 -10
- data/test/certificates/invalid_rsa_private_key1 +0 -1
- data/test/certificates/invalid_rsa_private_key2 +0 -1
- data/test/certificates/invalid_rsa_private_key3 +0 -10
- data/test/certificates/ruby-saml-2.crt +0 -15
- data/test/certificates/ruby-saml.crt +0 -14
- data/test/certificates/ruby-saml.key +0 -15
- data/test/idp_metadata_parser_test.rb +0 -587
- data/test/logging_test.rb +0 -62
- data/test/logout_requests/invalid_slo_request.xml +0 -6
- data/test/logout_requests/slo_request.xml +0 -4
- data/test/logout_requests/slo_request.xml.base64 +0 -1
- data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
- data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
- data/test/logout_requests/slo_request_with_session_index.xml +0 -5
- data/test/logout_responses/logoutresponse_fixtures.rb +0 -86
- data/test/logoutrequest_test.rb +0 -260
- data/test/logoutresponse_test.rb +0 -409
- data/test/metadata/idp_descriptor.xml +0 -26
- data/test/metadata/idp_descriptor_2.xml +0 -56
- data/test/metadata/idp_descriptor_3.xml +0 -14
- data/test/metadata/idp_descriptor_4.xml +0 -72
- data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
- data/test/metadata/idp_metadata_multi_certs.xml +0 -75
- data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
- data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
- data/test/metadata/idp_multiple_descriptors.xml +0 -59
- data/test/metadata/idp_multiple_descriptors_2.xml +0 -59
- data/test/metadata/no_idp_descriptor.xml +0 -21
- data/test/metadata_test.rb +0 -331
- data/test/request_test.rb +0 -340
- data/test/response_test.rb +0 -1620
- data/test/responses/adfs_response_sha1.xml +0 -46
- data/test/responses/adfs_response_sha256.xml +0 -46
- data/test/responses/adfs_response_sha384.xml +0 -46
- data/test/responses/adfs_response_sha512.xml +0 -46
- data/test/responses/adfs_response_xmlns.xml +0 -45
- data/test/responses/attackxee.xml +0 -13
- data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
- data/test/responses/invalids/empty_destination.xml.base64 +0 -1
- data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
- data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
- data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
- data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
- data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
- data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
- data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
- data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
- data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
- data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
- data/test/responses/invalids/no_conditions.xml.base64 +0 -1
- data/test/responses/invalids/no_id.xml.base64 +0 -1
- data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
- data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
- data/test/responses/invalids/no_nameid.xml.base64 +0 -1
- data/test/responses/invalids/no_saml2.xml.base64 +0 -1
- data/test/responses/invalids/no_signature.xml.base64 +0 -1
- data/test/responses/invalids/no_status.xml.base64 +0 -1
- data/test/responses/invalids/no_status_code.xml.base64 +0 -1
- data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
- data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
- data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
- data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
- data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
- data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
- data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
- data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
- data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
- data/test/responses/no_signature_ns.xml +0 -48
- data/test/responses/open_saml_response.xml +0 -56
- data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
- data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
- data/test/responses/response_double_status_code.xml.base64 +0 -1
- data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
- data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
- data/test/responses/response_eval.xml +0 -7
- data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
- data/test/responses/response_node_text_attack.xml.base64 +0 -1
- data/test/responses/response_node_text_attack2.xml.base64 +0 -1
- data/test/responses/response_node_text_attack3.xml.base64 +0 -1
- data/test/responses/response_unsigned_xml_base64 +0 -1
- data/test/responses/response_with_ampersands.xml +0 -139
- data/test/responses/response_with_ampersands.xml.base64 +0 -93
- data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
- data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
- data/test/responses/response_with_multiple_attribute_values.xml +0 -67
- data/test/responses/response_with_retrieval_method.xml +0 -26
- data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
- data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
- data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
- data/test/responses/response_with_signed_assertion_3.xml +0 -30
- data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
- data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
- data/test/responses/response_without_attributes.xml.base64 +0 -79
- data/test/responses/response_without_reference_uri.xml.base64 +0 -1
- data/test/responses/response_wrapped.xml.base64 +0 -150
- data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
- data/test/responses/signed_nameid_in_atts.xml +0 -47
- data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
- data/test/responses/simple_saml_php.xml +0 -71
- data/test/responses/starfield_response.xml.base64 +0 -1
- data/test/responses/test_sign.xml +0 -43
- data/test/responses/unsigned_encrypted_adfs.xml +0 -23
- data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
- data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
- data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
- data/test/responses/valid_response.xml.base64 +0 -1
- data/test/responses/valid_response_with_formatted_x509certificate.xml.base64 +0 -1
- data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
- data/test/saml_message_test.rb +0 -56
- data/test/settings_test.rb +0 -329
- data/test/slo_logoutrequest_test.rb +0 -448
- data/test/slo_logoutresponse_test.rb +0 -233
- data/test/test_helper.rb +0 -331
- data/test/utils_test.rb +0 -259
- data/test/xml_security_test.rb +0 -421
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA256:
|
3
|
-
|
4
|
-
|
5
|
-
SHA512:
|
6
|
-
|
7
|
-
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 25c4115dff650511c702291e7e6e3277a2c50c43b603c4cf68ae1473b3c061b5
|
4
|
+
data.tar.gz: 375b631e4059b50e112f4fc5b890e48c000ddae894fdef7cc665b9a58bad5b7a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1207da19dae7cb853704a0dbbd1d55791156d6703a5d3162adaa4d47ea1e645e4806687392db53c8c3e9c0a51b2fbb45772b8202975565f9157d32b707fd56a1
|
7
|
+
data.tar.gz: 9a4a9ba94e5ffd0eb24ef08e4a45435dec63333b2cbf1a0f0ecc164ce0569bb8720941c88874d64aef8524bebb5209bd70299e0e5bbdc953b7546aa055da58be
|
data/.travis.yml
CHANGED
@@ -1,19 +1,18 @@
|
|
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.
|
8
|
-
- 2.2.
|
9
|
-
- 2.3.
|
10
|
-
- 2.4.
|
11
|
-
- 2.5.
|
12
|
-
- 2.6.
|
13
|
-
-
|
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
|
14
13
|
- jruby-1.7.27
|
15
14
|
- jruby-9.1.17.0
|
16
|
-
- jruby-9.2.
|
15
|
+
- jruby-9.2.13.0
|
17
16
|
gemfile:
|
18
17
|
- Gemfile
|
19
18
|
- gemfiles/nokogiri-1.5.gemfile
|
@@ -21,27 +20,29 @@ before_install:
|
|
21
20
|
- gem update bundler
|
22
21
|
matrix:
|
23
22
|
exclude:
|
24
|
-
- rvm: 1.8.7
|
25
|
-
gemfile: Gemfile
|
26
|
-
- rvm: ree
|
27
|
-
gemfile: Gemfile
|
28
23
|
- rvm: jruby-1.7.27
|
29
24
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
30
25
|
- rvm: jruby-9.1.17.0
|
31
26
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
32
|
-
- rvm: jruby-9.2.
|
27
|
+
- rvm: jruby-9.2.13.0
|
33
28
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
34
29
|
- rvm: 2.1.5
|
35
30
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
36
|
-
- rvm: 2.
|
31
|
+
- rvm: 2.1.10
|
37
32
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
38
|
-
- rvm: 2.
|
33
|
+
- rvm: 2.2.10
|
39
34
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
40
|
-
- rvm: 2.
|
35
|
+
- rvm: 2.3.8
|
41
36
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
42
|
-
- rvm: 2.
|
37
|
+
- rvm: 2.4.6
|
43
38
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
44
|
-
- rvm: 2.
|
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
|
45
46
|
gemfile: gemfiles/nokogiri-1.5.gemfile
|
46
47
|
env:
|
47
48
|
- JRUBY_OPTS="--debug"
|
data/README.md
CHANGED
@@ -1,6 +1,22 @@
|
|
1
|
-
# Ruby SAML [](http://travis-ci.org/onelogin/ruby-saml) [](http://travis-ci.org/onelogin/ruby-saml) [](https://coveralls.io/r/onelogin/ruby-saml?branch=master)
|
2
2
|
|
3
|
-
|
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
|
+
`idp_sso_target_url` and `idp_slo_target_url` attributes of the Settings class deprecated in favor of `idp_sso_service_url` and `idp_slo_service_url`.
|
8
|
+
In IDPMetadataParser, `parse`, `parse_to_hash` and `parse_to_array` methods now retrieve SSO URL and SLO URL endpoints with
|
9
|
+
`idp_sso_service_url` and `idp_slo_service_url` (previously `idp_sso_target_url` and `idp_slo_target_url` respectively).
|
10
|
+
|
11
|
+
## Updating from 1.10.x to 1.11.0
|
12
|
+
Version `1.11.0` deprecates the use of `settings.issuer` in favour of `settings.sp_entity_id`.
|
13
|
+
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.
|
14
|
+
|
15
|
+
Version `1.10.2` includes the `valid_until` attribute in parsed IdP metadata.
|
16
|
+
|
17
|
+
Version `1.10.1` improves Ruby 1.8.7 support.
|
18
|
+
|
19
|
+
## Updating from 1.9.0 to 1.10.0
|
4
20
|
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/
|
5
21
|
|
6
22
|
## Updating from 1.8.0 to 1.9.0
|
@@ -107,9 +123,12 @@ We created a demo project for Rails4 that uses the latest version of this librar
|
|
107
123
|
* 2.4.x
|
108
124
|
* 2.5.x
|
109
125
|
* 2.6.x
|
110
|
-
*
|
111
|
-
*
|
112
|
-
* JRuby
|
126
|
+
* 2.7.x
|
127
|
+
* 3.0.x
|
128
|
+
* JRuby 1.7.x
|
129
|
+
* JRuby 9.0.x
|
130
|
+
* JRuby 9.1.x
|
131
|
+
* JRuby 9.2.x
|
113
132
|
|
114
133
|
## Adding Features, Pull Requests
|
115
134
|
* Fork the repository
|
@@ -123,6 +142,17 @@ We created a demo project for Rails4 that uses the latest version of this librar
|
|
123
142
|
|
124
143
|
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.
|
125
144
|
|
145
|
+
### Security warning
|
146
|
+
|
147
|
+
Some tools may incorrectly report ruby-saml is a potential security vulnerability.
|
148
|
+
ruby-saml depends on Nokogiri, and it's possible to use Nokogiri in a dangerous way
|
149
|
+
(by enabling its DTDLOAD option and disabling its NONET option).
|
150
|
+
This dangerous Nokogiri configuration, which is sometimes used by other components,
|
151
|
+
can create an XML External Entity (XXE) vulnerability if the XML data is not trusted.
|
152
|
+
However, ruby-saml never enables this dangerous Nokogiri configuration;
|
153
|
+
ruby-saml never enables DTDLOAD, and it never disables NONET.
|
154
|
+
|
155
|
+
|
126
156
|
## Getting Started
|
127
157
|
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:
|
128
158
|
|
@@ -130,7 +160,7 @@ Using `Gemfile`
|
|
130
160
|
|
131
161
|
```ruby
|
132
162
|
# latest stable
|
133
|
-
gem 'ruby-saml', '~> 1.
|
163
|
+
gem 'ruby-saml', '~> 1.11.0'
|
134
164
|
|
135
165
|
# or track master for bleeding-edge
|
136
166
|
gem 'ruby-saml', :github => 'onelogin/ruby-saml'
|
@@ -217,6 +247,7 @@ def consume
|
|
217
247
|
session[:attributes] = response.attributes
|
218
248
|
else
|
219
249
|
authorize_failure # This method shows an error message
|
250
|
+
# List of errors is available in response.errors array
|
220
251
|
end
|
221
252
|
end
|
222
253
|
```
|
@@ -238,10 +269,10 @@ def saml_settings
|
|
238
269
|
settings = OneLogin::RubySaml::Settings.new
|
239
270
|
|
240
271
|
settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
|
241
|
-
settings.
|
272
|
+
settings.sp_entity_id = "http://#{request.host}/saml/metadata"
|
242
273
|
settings.idp_entity_id = "https://app.onelogin.com/saml/metadata/#{OneLoginAppId}"
|
243
|
-
settings.
|
244
|
-
settings.
|
274
|
+
settings.idp_sso_service_url = "https://app.onelogin.com/trust/saml2/http-post/sso/#{OneLoginAppId}"
|
275
|
+
settings.idp_slo_service_url = "https://app.onelogin.com/trust/saml2/http-redirect/slo/#{OneLoginAppId}"
|
245
276
|
settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint
|
246
277
|
settings.idp_cert_fingerprint_algorithm = "http://www.w3.org/2000/09/xmldsig#sha1"
|
247
278
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
@@ -262,6 +293,8 @@ def saml_settings
|
|
262
293
|
end
|
263
294
|
```
|
264
295
|
|
296
|
+
The use of settings.issuer is deprecated in favour of settings.sp_entity_id since version 1.11.0
|
297
|
+
|
265
298
|
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:
|
266
299
|
|
267
300
|
```ruby
|
@@ -269,6 +302,7 @@ response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_authnst
|
|
269
302
|
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_conditions: true}) # skips conditions
|
270
303
|
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_subject_confirmation: true}) # skips subject confirmation
|
271
304
|
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
|
305
|
+
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], {skip_audience: true}) # skips audience check
|
272
306
|
```
|
273
307
|
|
274
308
|
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:
|
@@ -292,6 +326,7 @@ class SamlController < ApplicationController
|
|
292
326
|
session[:attributes] = response.attributes
|
293
327
|
else
|
294
328
|
authorize_failure # This method shows an error message
|
329
|
+
# List of errors is available in response.errors array
|
295
330
|
end
|
296
331
|
end
|
297
332
|
|
@@ -301,8 +336,8 @@ class SamlController < ApplicationController
|
|
301
336
|
settings = OneLogin::RubySaml::Settings.new
|
302
337
|
|
303
338
|
settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
|
304
|
-
settings.
|
305
|
-
settings.
|
339
|
+
settings.sp_entity_id = "http://#{request.host}/saml/metadata"
|
340
|
+
settings.idp_sso_service_url = "https://app.onelogin.com/saml/signon/#{OneLoginAppId}"
|
306
341
|
settings.idp_cert_fingerprint = OneLoginAppCertFingerPrint
|
307
342
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
308
343
|
|
@@ -364,7 +399,7 @@ def saml_settings
|
|
364
399
|
settings = idp_metadata_parser.parse_remote("https://example.com/auth/saml2/idp/metadata")
|
365
400
|
|
366
401
|
settings.assertion_consumer_service_url = "http://#{request.host}/saml/consume"
|
367
|
-
settings.
|
402
|
+
settings.sp_entity_id = "http://#{request.host}/saml/metadata"
|
368
403
|
settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
|
369
404
|
# Optional for most SAML IdPs
|
370
405
|
settings.authn_context = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
|
@@ -375,11 +410,11 @@ end
|
|
375
410
|
The following attributes are set:
|
376
411
|
* idp_entity_id
|
377
412
|
* name_identifier_format
|
378
|
-
*
|
379
|
-
*
|
413
|
+
* idp_sso_service_url
|
414
|
+
* idp_slo_service_url
|
380
415
|
* idp_attribute_names
|
381
|
-
* idp_cert
|
382
|
-
* idp_cert_fingerprint
|
416
|
+
* idp_cert
|
417
|
+
* idp_cert_fingerprint
|
383
418
|
* idp_cert_multi
|
384
419
|
|
385
420
|
### Retrieve one Entity Descriptor when many exist in Metadata
|
@@ -442,6 +477,9 @@ Imagine this `saml:AttributeStatement`
|
|
442
477
|
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
|
443
478
|
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="1"/>
|
444
479
|
</saml:Attribute>
|
480
|
+
<saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
|
481
|
+
<saml:AttributeValue>usersName</saml:AttributeValue>
|
482
|
+
</saml:Attribute>
|
445
483
|
</saml:AttributeStatement>
|
446
484
|
```
|
447
485
|
|
@@ -452,7 +490,8 @@ pp(response.attributes) # is an OneLogin::RubySaml::Attributes object
|
|
452
490
|
"another_value"=>["value1", "value2"],
|
453
491
|
"role"=>["role1", "role2", "role3"],
|
454
492
|
"attribute_with_nil_value"=>[nil],
|
455
|
-
"attribute_with_nils_and_empty_strings"=>["", "valuePresent", nil, nil]
|
493
|
+
"attribute_with_nils_and_empty_strings"=>["", "valuePresent", nil, nil]
|
494
|
+
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname"=>["usersName"]}>
|
456
495
|
|
457
496
|
# Active single_value_compatibility
|
458
497
|
OneLogin::RubySaml::Attributes.single_value_compatibility = true
|
@@ -469,6 +508,9 @@ pp(response.attributes.single(:role))
|
|
469
508
|
pp(response.attributes.multi(:role))
|
470
509
|
# => ["role1", "role2", "role3"]
|
471
510
|
|
511
|
+
pp(response.attributes.fetch(:role))
|
512
|
+
# => "role1"
|
513
|
+
|
472
514
|
pp(response.attributes[:attribute_with_nil_value])
|
473
515
|
# => nil
|
474
516
|
|
@@ -484,6 +526,9 @@ pp(response.attributes.single(:not_exists))
|
|
484
526
|
pp(response.attributes.multi(:not_exists))
|
485
527
|
# => nil
|
486
528
|
|
529
|
+
pp(response.attributes.fetch(/givenname/))
|
530
|
+
# => "usersName"
|
531
|
+
|
487
532
|
# Deactive single_value_compatibility
|
488
533
|
OneLogin::RubySaml::Attributes.single_value_compatibility = false
|
489
534
|
|
@@ -499,6 +544,9 @@ pp(response.attributes.single(:role))
|
|
499
544
|
pp(response.attributes.multi(:role))
|
500
545
|
# => ["role1", "role2", "role3"]
|
501
546
|
|
547
|
+
pp(response.attributes.fetch(:role))
|
548
|
+
# => ["role1", "role2", "role3"]
|
549
|
+
|
502
550
|
pp(response.attributes[:attribute_with_nil_value])
|
503
551
|
# => [nil]
|
504
552
|
|
@@ -513,12 +561,15 @@ pp(response.attributes.single(:not_exists))
|
|
513
561
|
|
514
562
|
pp(response.attributes.multi(:not_exists))
|
515
563
|
# => nil
|
564
|
+
|
565
|
+
pp(response.attributes.fetch(/givenname/))
|
566
|
+
# => ["usersName"]
|
516
567
|
```
|
517
568
|
|
518
569
|
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').
|
519
570
|
To add a `saml:AuthnContextDeclRef`, define `settings.authn_context_decl_ref`.
|
520
571
|
|
521
|
-
In a SP-
|
572
|
+
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
|
522
573
|
building the authrequest object.
|
523
574
|
|
524
575
|
|
@@ -548,6 +599,8 @@ The settings related to sign are stored in the `security` attribute of the setti
|
|
548
599
|
# Embeded signature or HTTP GET parameter signature
|
549
600
|
# Note that metadata signature is always embedded regardless of this value.
|
550
601
|
settings.security[:embed_sign] = false
|
602
|
+
settings.security[:check_idp_cert_expiration] = false # Enable or not IdP x509 cert expiration check
|
603
|
+
settings.security[:check_sp_cert_expiration] = false # Enable or not SP x509 cert expiration check
|
551
604
|
```
|
552
605
|
|
553
606
|
Notice that the RelayState parameter is used when creating the Signature on the HTTP-Redirect Binding.
|
@@ -555,7 +608,7 @@ Remember to provide it to the Signature builder if you are sending a `GET RelayS
|
|
555
608
|
signature validation process will fail at the Identity Provider.
|
556
609
|
|
557
610
|
The Service Provider will sign the request/responses with its private key.
|
558
|
-
The Identity Provider will validate the sign of the received request/responses with the public
|
611
|
+
The Identity Provider will validate the sign of the received request/responses with the public x509 cert of the
|
559
612
|
Service Provider.
|
560
613
|
|
561
614
|
Notice that this toolkit uses 'settings.certificate' and 'settings.private_key' for the sign and decrypt processes.
|
@@ -596,21 +649,27 @@ def sp_logout_request
|
|
596
649
|
# LogoutRequest accepts plain browser requests w/o paramters
|
597
650
|
settings = saml_settings
|
598
651
|
|
599
|
-
if settings.
|
652
|
+
if settings.idp_slo_service_url.nil?
|
600
653
|
logger.info "SLO IdP Endpoint not found in settings, executing then a normal logout'"
|
601
654
|
delete_session
|
602
655
|
else
|
603
656
|
|
604
|
-
# Since we created a new SAML request, save the transaction_id
|
605
|
-
# to compare it with the response we get back
|
606
657
|
logout_request = OneLogin::RubySaml::Logoutrequest.new()
|
607
|
-
session[:
|
608
|
-
logger.info "New SP SLO for userid '#{session[:userid]}' transactionid '#{session[:transaction_id]}'"
|
658
|
+
logger.info "New SP SLO for userid '#{session[:userid]}' transactionid '#{logout_request.uuid}'"
|
609
659
|
|
610
660
|
if settings.name_identifier_value.nil?
|
611
661
|
settings.name_identifier_value = session[:userid]
|
612
662
|
end
|
613
663
|
|
664
|
+
# Ensure user is logged out before redirect to IdP, in case anything goes wrong during single logout process (as recommended by saml2int [SDP-SP34])
|
665
|
+
logged_user = session[:userid]
|
666
|
+
logger.info "Delete session for '#{session[:userid]}'"
|
667
|
+
delete_session
|
668
|
+
|
669
|
+
# Save the transaction_id to compare it with the response we get back
|
670
|
+
session[:transaction_id] = logout_request.uuid
|
671
|
+
session[:logged_out_user] = logged_user
|
672
|
+
|
614
673
|
relayState = url_for controller: 'saml', action: 'index'
|
615
674
|
redirect_to(logout_request.create(settings, :RelayState => relayState))
|
616
675
|
end
|
@@ -638,7 +697,7 @@ def process_logout_response
|
|
638
697
|
logger.error "The SAML Logout Response is invalid"
|
639
698
|
else
|
640
699
|
# Actually log out this session
|
641
|
-
logger.info "
|
700
|
+
logger.info "SLO completed for '#{session[:logged_out_user]}'"
|
642
701
|
delete_session
|
643
702
|
end
|
644
703
|
end
|
@@ -647,6 +706,8 @@ end
|
|
647
706
|
def delete_session
|
648
707
|
session[:userid] = nil
|
649
708
|
session[:attributes] = nil
|
709
|
+
session[:transaction_id] = nil
|
710
|
+
session[:logged_out_user] = nil
|
650
711
|
end
|
651
712
|
```
|
652
713
|
|
@@ -659,7 +720,7 @@ def idp_logout_request
|
|
659
720
|
logout_request = OneLogin::RubySaml::SloLogoutrequest.new(params[:SAMLRequest])
|
660
721
|
if !logout_request.is_valid?
|
661
722
|
logger.error "IdP initiated LogoutRequest was not valid!"
|
662
|
-
render :inline => logger.error
|
723
|
+
return render :inline => logger.error
|
663
724
|
end
|
664
725
|
logger.info "IdP initiated Logout for #{logout_request.name_id}"
|
665
726
|
|
@@ -714,6 +775,14 @@ class SamlController < ApplicationController
|
|
714
775
|
end
|
715
776
|
```
|
716
777
|
|
778
|
+
You can add ValidUntil and CacheDuration to the XML Metadata using instead
|
779
|
+
```ruby
|
780
|
+
# Valid until => 2 days from now
|
781
|
+
# Cache duration = 604800s = 1 week
|
782
|
+
valid_until = Time.now + 172800
|
783
|
+
cache_duration = 604800
|
784
|
+
meta.generate(settings, false, valid_until, cache_duration)
|
785
|
+
```
|
717
786
|
|
718
787
|
## Clock Drift
|
719
788
|
|
data/changelog.md
CHANGED
@@ -1,4 +1,44 @@
|
|
1
1
|
# RubySaml Changelog
|
2
|
+
|
3
|
+
### 1.12.2 (Apr 08, 2022)
|
4
|
+
* [575](https://github.com/onelogin/ruby-saml/pull/575) Fix SloLogoutresponse bug on LogoutRequest
|
5
|
+
|
6
|
+
### 1.12.1 (Apr 05, 2022)
|
7
|
+
* Fix XPath typo incompatible with Rexml 3.2.5
|
8
|
+
* Refactor GCM support
|
9
|
+
|
10
|
+
### 1.12.0 (Feb 18, 2021)
|
11
|
+
* Support AES-128-GCM, AES-192-GCM, and AES-256-GCM encryptions
|
12
|
+
* Parse & return SLO ResponseLocation in IDPMetadataParser & Settings
|
13
|
+
* Adding idp_sso_service_url and idp_slo_service_url settings
|
14
|
+
* [#536](https://github.com/onelogin/ruby-saml/pull/536) Adding feth method to be able retrieve attributes based on regex
|
15
|
+
* Reduce size of built gem by excluding the test folder
|
16
|
+
* Improve protection on Zlib deflate decompression bomb attack.
|
17
|
+
* Add ValidUntil and cacheDuration support on Metadata generator
|
18
|
+
* Add support for cacheDuration at the IdpMetadataParser
|
19
|
+
* Support customizable statusCode on generated LogoutResponse
|
20
|
+
* [#545](https://github.com/onelogin/ruby-saml/pull/545) More specific error messages for signature validation
|
21
|
+
* Support Process Transform
|
22
|
+
* Raise SettingError if invoking an action with no endpoint defined on the settings
|
23
|
+
* Made IdpMetadataParser more extensible for subclasses
|
24
|
+
*[#548](https://github.com/onelogin/ruby-saml/pull/548) Add :skip_audience option
|
25
|
+
* [#555](https://github.com/onelogin/ruby-saml/pull/555) Define 'soft' variable to prevent exception when doc cert is invalid
|
26
|
+
* Improve documentation
|
27
|
+
|
28
|
+
### 1.11.0 (Jul 24, 2019)
|
29
|
+
|
30
|
+
* Deprecate settings.issuer in favor of settings.sp_entity_id
|
31
|
+
* Add support for certification expiration
|
32
|
+
|
33
|
+
### 1.10.2 (Apr 29, 2019)
|
34
|
+
|
35
|
+
* Add valid until, accessor
|
36
|
+
* Fix Rubygem metadata that requested nokogiri <= 1.5.11
|
37
|
+
|
38
|
+
### 1.10.1 (Apr 08, 2019)
|
39
|
+
|
40
|
+
* Fix ruby 1.8.7 incompatibilities
|
41
|
+
|
2
42
|
### 1.10.0 (Mar 21, 2019)
|
3
43
|
* Add Subject support on AuthNRequest to allow SPs provide info to the IdP about the user to be authenticated
|
4
44
|
* Improves IdpMetadataParser to allow parse multiple IDPSSODescriptors
|
@@ -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 [
|
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.respond_to? :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
|