ruby-saml 1.13.0 → 1.15.0
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 +5 -5
- data/.github/workflows/test.yml +20 -2
- data/CHANGELOG.md +13 -0
- data/LICENSE +2 -1
- data/README.md +79 -6
- data/UPGRADING.md +1 -1
- data/lib/onelogin/ruby-saml/authrequest.rb +2 -2
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +1 -1
- data/lib/onelogin/ruby-saml/logoutrequest.rb +2 -2
- data/lib/onelogin/ruby-saml/logoutresponse.rb +1 -1
- data/lib/onelogin/ruby-saml/metadata.rb +1 -1
- data/lib/onelogin/ruby-saml/response.rb +7 -2
- data/lib/onelogin/ruby-saml/saml_message.rb +2 -3
- data/lib/onelogin/ruby-saml/settings.rb +9 -12
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +1 -26
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +2 -2
- data/lib/onelogin/ruby-saml/utils.rb +20 -6
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +2 -2
- data/ruby-saml.gemspec +40 -12
- metadata +43 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3ed3b0ab8cb9f9fd8b4e23b34f8ad06fd1e6c6a13d885d34c2f7b385297783b3
|
4
|
+
data.tar.gz: 757dccd6c1418f1128a69c7fdcd95cdd8d8bcac697ae750edb92f058aee50c7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cc12490c6b57281677f1db5a5a804c07a9b97f57a86d3b5676b79b36ca28bd7d9971ed3db893b730ff09ab6c03374600d87118949440c4271293bc48333b3d6
|
7
|
+
data.tar.gz: 4c330a53de476f479a22dbe07b18f51e0ebe1dcde834eac9cb65678b8767094e365a0ea043a5e4b09d1cabfa6a8f0c4287f29fffe6e53328b70572a64cefcd04
|
data/.github/workflows/test.yml
CHANGED
@@ -8,8 +8,8 @@ jobs:
|
|
8
8
|
strategy:
|
9
9
|
fail-fast: false
|
10
10
|
matrix:
|
11
|
-
os: [ubuntu-
|
12
|
-
ruby-version: [2.1.9, 2.2.10, 2.3.8, 2.4.6, 2.5.8, 2.6.6, 2.7.2, 3.0.1, jruby-9.1.17.0, jruby-9.2.17.0, truffleruby]
|
11
|
+
os: [ubuntu-20.04, macos-latest]
|
12
|
+
ruby-version: [2.1.9, 2.2.10, 2.3.8, 2.4.6, 2.5.8, 2.6.6, 2.7.2, 3.0.1, 3.1, 3.2, jruby-9.1.17.0, jruby-9.2.17.0, jruby-9.3.2.0, jruby-9.4.0.0, truffleruby]
|
13
13
|
runs-on: ${{ matrix.os }}
|
14
14
|
steps:
|
15
15
|
- uses: actions/checkout@v2
|
@@ -23,3 +23,21 @@ jobs:
|
|
23
23
|
|
24
24
|
- name: Run tests
|
25
25
|
run: bundle exec rake
|
26
|
+
|
27
|
+
- name: Coveralls
|
28
|
+
uses: coverallsapp/github-action@master
|
29
|
+
with:
|
30
|
+
github-token: ${{ secrets.github_token }}
|
31
|
+
parallel: true
|
32
|
+
flag-name: run-${{ matrix.ruby-version }}
|
33
|
+
|
34
|
+
finish:
|
35
|
+
needs: test
|
36
|
+
runs-on: ubuntu-latest
|
37
|
+
steps:
|
38
|
+
- name: Coveralls Finished
|
39
|
+
uses: coverallsapp/github-action@master
|
40
|
+
with:
|
41
|
+
github-token: ${{ secrets.github_token }}
|
42
|
+
flag-name: run-${{ matrix.ruby-version }}
|
43
|
+
parallel-finished: true
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,17 @@
|
|
1
1
|
# Ruby SAML Changelog
|
2
|
+
### 1.15.0 (Jan 04, 2023)
|
3
|
+
* [#650](https://github.com/SAML-Toolkits/ruby-saml/pull/650) Replace strip! by strip on compute_digest method
|
4
|
+
* [#638](https://github.com/SAML-Toolkits/ruby-saml/pull/638) Fix dateTime format for the validUntil attribute of the generated metadata
|
5
|
+
* [#576](https://github.com/SAML-Toolkits/ruby-saml/pull/576) Support idp cert multi with string keys
|
6
|
+
* [#567](https://github.com/SAML-Toolkits/ruby-saml/pull/567) Improve Code quality
|
7
|
+
* Add info about new repo, new maintainer, new security contact
|
8
|
+
* Fix tests, Adjust dependencies, Add ruby 3.2 and new jruby versions tests to the CI. Add coveralls support
|
9
|
+
|
10
|
+
### 1.14.0 (Feb 01, 2022)
|
11
|
+
* [#627](https://github.com/onelogin/ruby-saml/pull/627) Support escape downcasing for validating SLO Signatures of ADFS/Azure
|
12
|
+
* [#633](https://github.com/onelogin/ruby-saml/pull/633) Support ability to change ID prefix
|
13
|
+
* Make the uuid editable on the SAML Messages generated by the toolkit
|
14
|
+
* [#622](https://github.com/onelogin/ruby-saml/pull/622) Add security setting to more strictly enforce audience validation
|
2
15
|
|
3
16
|
### 1.13.0 (Sept 06, 2021)
|
4
17
|
* [#611](https://github.com/onelogin/ruby-saml/pull/601) Replace MAX_BYTE_SIZE constant with setting: message_max_bytesize
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -14,7 +14,7 @@ requests from identity providers.
|
|
14
14
|
SAML authorization is a two step process and you are expected to implement support for both.
|
15
15
|
|
16
16
|
We created a demo project for Rails 4 that uses the latest version of this library:
|
17
|
-
[ruby-saml-example](https://github.com/
|
17
|
+
[ruby-saml-example](https://github.com/saml-toolkit/ruby-saml-example)
|
18
18
|
|
19
19
|
### Supported Ruby Versions
|
20
20
|
|
@@ -52,8 +52,7 @@ In addition, the following may work but are untested:
|
|
52
52
|
## Security Guidelines
|
53
53
|
|
54
54
|
If you believe you have discovered a security vulnerability in this gem, please report it
|
55
|
-
|
56
|
-
guidelines, and will work with you to quickly find a resolution.
|
55
|
+
by mail to the maintainer: sixto.martin.garcia+security@gmail.com
|
57
56
|
|
58
57
|
### Security Warning
|
59
58
|
|
@@ -66,7 +65,7 @@ However, ruby-saml never enables this dangerous Nokogiri configuration;
|
|
66
65
|
ruby-saml never enables DTDLOAD, and it never disables NONET.
|
67
66
|
|
68
67
|
The OneLogin::RubySaml::IdpMetadataParser class does not validate in any way the URL
|
69
|
-
that is introduced in order to be parsed.
|
68
|
+
that is introduced in order to be parsed.
|
70
69
|
|
71
70
|
Usually the same administrator that handles the Service Provider also sets the URL to
|
72
71
|
the IdP, which should be a trusted resource.
|
@@ -87,7 +86,7 @@ Using `Gemfile`
|
|
87
86
|
gem 'ruby-saml', '~> 1.11.0'
|
88
87
|
|
89
88
|
# or track master for bleeding-edge
|
90
|
-
gem 'ruby-saml', :github => '
|
89
|
+
gem 'ruby-saml', :github => 'saml-toolkit/ruby-saml'
|
91
90
|
```
|
92
91
|
|
93
92
|
Using RubyGems
|
@@ -392,6 +391,51 @@ The `OneLogin::RubySaml::IdpMetadataParser` also provides the methods `#parse_to
|
|
392
391
|
Those return an Hash instead of a `Settings` object, which may be useful for configuring
|
393
392
|
[omniauth-saml](https://github.com/omniauth/omniauth-saml), for instance.
|
394
393
|
|
394
|
+
|
395
|
+
### Validating Signature of Metadata and retrieve settings
|
396
|
+
|
397
|
+
Right now there is no method at ruby_saml to validate the signature of the metadata that gonna be parsed,
|
398
|
+
but it can be done as follows:
|
399
|
+
* Download the XML.
|
400
|
+
* Validate the Signature, providing the cert.
|
401
|
+
* Provide the XML to the parse method if the signature was validated
|
402
|
+
|
403
|
+
```
|
404
|
+
require "xml_security"
|
405
|
+
require "onelogin/ruby-saml/utils"
|
406
|
+
require "onelogin/ruby-saml/idp_metadata_parser"
|
407
|
+
|
408
|
+
url = "<url_to_the_metadata>"
|
409
|
+
idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
|
410
|
+
|
411
|
+
uri = URI.parse(url)
|
412
|
+
raise ArgumentError.new("url must begin with http or https") unless /^https?/ =~ uri.scheme
|
413
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
414
|
+
if uri.scheme == "https"
|
415
|
+
http.use_ssl = true
|
416
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
417
|
+
end
|
418
|
+
|
419
|
+
get = Net::HTTP::Get.new(uri.request_uri)
|
420
|
+
get.basic_auth uri.user, uri.password if uri.user
|
421
|
+
response = http.request(get)
|
422
|
+
xml = response.body
|
423
|
+
errors = []
|
424
|
+
doc = XMLSecurity::SignedDocument.new(xml, errors)
|
425
|
+
cert_str = "<include_cert_here>"
|
426
|
+
cert = OneLogin::RubySaml::Utils.format_cert("cert_str")
|
427
|
+
metadata_sign_cert = OpenSSL::X509::Certificate.new(cert)
|
428
|
+
valid = doc.validate_document_with_cert(metadata_sign_cert, true)
|
429
|
+
if valid
|
430
|
+
settings = idp_metadata_parser.parse(
|
431
|
+
xml,
|
432
|
+
entity_id: "<entity_id_of_the_entity_to_be_retrieved>"
|
433
|
+
)
|
434
|
+
else
|
435
|
+
print "Metadata Signarture failed to be verified with the cert provided"
|
436
|
+
end
|
437
|
+
|
438
|
+
|
395
439
|
## Retrieving Attributes
|
396
440
|
|
397
441
|
If you are using `saml:AttributeStatement` to transfer data like the username, you can access all the attributes through `response.attributes`. It contains all the `saml:AttributeStatement`s with its 'Name' as an indifferent key and one or more `saml:AttributeValue`s as values. The value returned depends on the value of the
|
@@ -664,6 +708,29 @@ validation fails. You may disable such exceptions using the `settings.security[:
|
|
664
708
|
settings.security[:soft] = true # Do not raise error on failed signature/certificate validations
|
665
709
|
```
|
666
710
|
|
711
|
+
#### Audience Validation
|
712
|
+
|
713
|
+
A service provider should only consider a SAML response valid if the IdP includes an <AudienceRestriction>
|
714
|
+
element containting an <Audience> element that uniquely identifies the service provider. Unless you specify
|
715
|
+
the `skip_audience` option, Ruby SAML will validate that each SAML response includes an <Audience> element
|
716
|
+
whose contents matches `settings.sp_entity_id`.
|
717
|
+
|
718
|
+
By default, Ruby SAML considers an <AudienceRestriction> element containing only empty <Audience> elements
|
719
|
+
to be valid. That means an otherwise valid SAML response with a condition like this would be valid:
|
720
|
+
|
721
|
+
```xml
|
722
|
+
<AudienceRestriction>
|
723
|
+
<Audience />
|
724
|
+
</AudienceRestriction>
|
725
|
+
```
|
726
|
+
|
727
|
+
You may enforce that an <AudienceRestriction> element containing only empty <Audience> elements
|
728
|
+
is invalid using the `settings.security[:strict_audience_validation]` parameter.
|
729
|
+
|
730
|
+
```ruby
|
731
|
+
settings.security[:strict_audience_validation] = true
|
732
|
+
```
|
733
|
+
|
667
734
|
#### Key Rollover
|
668
735
|
|
669
736
|
To update the SP X.509 certificate and private key without disruption of service, you may define the parameter
|
@@ -767,7 +834,13 @@ Here is an example that we could add to our previous controller to process a SAM
|
|
767
834
|
# Method to handle IdP initiated logouts
|
768
835
|
def idp_logout_request
|
769
836
|
settings = Account.get_saml_settings
|
770
|
-
|
837
|
+
# ADFS URL-Encodes SAML data as lowercase, and the toolkit by default uses
|
838
|
+
# uppercase. Turn it True for ADFS compatibility on signature verification
|
839
|
+
settings.security[:lowercase_url_encoding] = true
|
840
|
+
|
841
|
+
logout_request = OneLogin::RubySaml::SloLogoutrequest.new(
|
842
|
+
params[:SAMLRequest], settings: settings
|
843
|
+
)
|
771
844
|
if !logout_request.is_valid?
|
772
845
|
logger.error "IdP initiated LogoutRequest was not valid!"
|
773
846
|
return render :inline => logger.error
|
data/UPGRADING.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Ruby SAML Migration Guide
|
2
2
|
|
3
|
-
## Updating from 1.12.x to 1.13.0
|
3
|
+
## Updating from 1.12.x to 1.13.0
|
4
4
|
|
5
5
|
Version `1.13.0` adds `settings.idp_sso_service_binding` and `settings.idp_slo_service_binding`, and
|
6
6
|
deprecates `settings.security[:embed_sign]`. If specified, new binding parameters will be used in place of `:embed_sign`
|
@@ -15,7 +15,7 @@ module OneLogin
|
|
15
15
|
class Authrequest < SamlMessage
|
16
16
|
|
17
17
|
# AuthNRequest ID
|
18
|
-
|
18
|
+
attr_accessor :uuid
|
19
19
|
|
20
20
|
# Initializes the AuthNRequest. An Authrequest Object that is an extension of the SamlMessage class.
|
21
21
|
# Asigns an ID, a random uuid.
|
@@ -39,7 +39,7 @@ module OneLogin
|
|
39
39
|
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
40
40
|
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
41
41
|
params.each_pair do |key, value|
|
42
|
-
request_params << "&#{key
|
42
|
+
request_params << "&#{key}=#{CGI.escape(value.to_s)}"
|
43
43
|
end
|
44
44
|
raise SettingError.new "Invalid settings, idp_sso_service_url is not set!" if settings.idp_sso_service_url.nil? or settings.idp_sso_service_url.empty?
|
45
45
|
@login_url = settings.idp_sso_service_url + request_params
|
@@ -442,7 +442,7 @@ module OneLogin
|
|
442
442
|
priority = Array(priority)
|
443
443
|
if priority.any?
|
444
444
|
values = nodes.map(&:text)
|
445
|
-
|
445
|
+
priority.detect { |candidate| values.include?(candidate) }
|
446
446
|
else
|
447
447
|
nodes.first.text
|
448
448
|
end
|
@@ -12,7 +12,7 @@ module OneLogin
|
|
12
12
|
class Logoutrequest < SamlMessage
|
13
13
|
|
14
14
|
# Logout Request ID
|
15
|
-
|
15
|
+
attr_accessor :uuid
|
16
16
|
|
17
17
|
# Initializes the Logout Request. A Logoutrequest Object that is an extension of the SamlMessage class.
|
18
18
|
# Asigns an ID, a random uuid.
|
@@ -36,7 +36,7 @@ module OneLogin
|
|
36
36
|
saml_request = CGI.escape(params.delete("SAMLRequest"))
|
37
37
|
request_params = "#{params_prefix}SAMLRequest=#{saml_request}"
|
38
38
|
params.each_pair do |key, value|
|
39
|
-
request_params << "&#{key
|
39
|
+
request_params << "&#{key}=#{CGI.escape(value.to_s)}"
|
40
40
|
end
|
41
41
|
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if settings.idp_slo_service_url.nil? or settings.idp_slo_service_url.empty?
|
42
42
|
@logout_url = settings.idp_slo_service_url + request_params
|
@@ -212,7 +212,7 @@ module OneLogin
|
|
212
212
|
return true unless options.has_key? :get_params
|
213
213
|
return true unless options[:get_params].has_key? 'Signature'
|
214
214
|
|
215
|
-
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params])
|
215
|
+
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params], settings.security[:lowercase_url_encoding])
|
216
216
|
|
217
217
|
if options[:get_params]['SigAlg'].nil? && !options[:raw_get_params]['SigAlg'].nil?
|
218
218
|
options[:get_params]['SigAlg'] = CGI.unescape(options[:raw_get_params]['SigAlg'])
|
@@ -49,7 +49,7 @@ module OneLogin
|
|
49
49
|
root = meta_doc.add_element("md:EntityDescriptor", namespaces)
|
50
50
|
root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
|
51
51
|
root.attributes["entityID"] = settings.sp_entity_id if settings.sp_entity_id
|
52
|
-
root.attributes["validUntil"] = valid_until.strftime('%Y-%m-%dT%H:%M:%
|
52
|
+
root.attributes["validUntil"] = valid_until.utc.strftime('%Y-%m-%dT%H:%M:%SZ') if valid_until
|
53
53
|
root.attributes["cacheDuration"] = "PT" + cache_duration.to_s + "S" if cache_duration
|
54
54
|
root
|
55
55
|
end
|
@@ -613,7 +613,12 @@ module OneLogin
|
|
613
613
|
#
|
614
614
|
def validate_audience
|
615
615
|
return true if options[:skip_audience]
|
616
|
-
return true if
|
616
|
+
return true if settings.sp_entity_id.nil? || settings.sp_entity_id.empty?
|
617
|
+
|
618
|
+
if audiences.empty?
|
619
|
+
return true unless settings.security[:strict_audience_validation]
|
620
|
+
return append_error("Invalid Audiences. The <AudienceRestriction> element contained only empty <Audience> elements. Expected audience #{settings.sp_entity_id}.")
|
621
|
+
end
|
617
622
|
|
618
623
|
unless audiences.include? settings.sp_entity_id
|
619
624
|
s = audiences.count > 1 ? 's' : '';
|
@@ -736,7 +741,7 @@ module OneLogin
|
|
736
741
|
# @return [Boolean] True if the SessionNotOnOrAfter of the AuthnStatement is valid, otherwise (when expired) False if soft=True
|
737
742
|
# @raise [ValidationError] if soft == false and validation fails
|
738
743
|
#
|
739
|
-
def validate_session_expiration
|
744
|
+
def validate_session_expiration
|
740
745
|
return true if session_expires_at.nil?
|
741
746
|
|
742
747
|
now = Time.now.utc
|
@@ -4,7 +4,6 @@ require 'base64'
|
|
4
4
|
require 'nokogiri'
|
5
5
|
require 'rexml/document'
|
6
6
|
require 'rexml/xpath'
|
7
|
-
require 'thread'
|
8
7
|
require "onelogin/ruby-saml/error_handling"
|
9
8
|
|
10
9
|
# Only supports SAML 2.0
|
@@ -69,14 +68,14 @@ module OneLogin
|
|
69
68
|
xml = Nokogiri::XML(document.to_s) do |config|
|
70
69
|
config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
|
71
70
|
end
|
72
|
-
rescue
|
71
|
+
rescue StandardError => error
|
73
72
|
return false if soft
|
74
73
|
raise ValidationError.new("XML load failed: #{error.message}")
|
75
74
|
end
|
76
75
|
|
77
76
|
SamlMessage.schema.validate(xml).map do |schema_error|
|
78
77
|
return false if soft
|
79
|
-
raise ValidationError.new("#{schema_error.message}\n\n#{xml
|
78
|
+
raise ValidationError.new("#{schema_error.message}\n\n#{xml}")
|
80
79
|
end
|
81
80
|
end
|
82
81
|
|
@@ -20,7 +20,7 @@ module OneLogin
|
|
20
20
|
end
|
21
21
|
|
22
22
|
config.each do |k,v|
|
23
|
-
acc = "#{k
|
23
|
+
acc = "#{k}=".to_sym
|
24
24
|
if respond_to? acc
|
25
25
|
value = v.is_a?(Hash) ? v.dup : v
|
26
26
|
send(acc, value)
|
@@ -195,17 +195,13 @@ module OneLogin
|
|
195
195
|
|
196
196
|
certs = {:signing => [], :encryption => [] }
|
197
197
|
|
198
|
-
|
199
|
-
idp_cert_multi[
|
200
|
-
|
201
|
-
certs[:signing].push(OpenSSL::X509::Certificate.new(formatted_cert))
|
202
|
-
end
|
203
|
-
end
|
198
|
+
[:signing, :encryption].each do |type|
|
199
|
+
certs_for_type = idp_cert_multi[type] || idp_cert_multi[type.to_s]
|
200
|
+
next if !certs_for_type || certs_for_type.empty?
|
204
201
|
|
205
|
-
|
206
|
-
idp_cert_multi[:encryption].each do |idp_cert|
|
202
|
+
certs_for_type.each do |idp_cert|
|
207
203
|
formatted_cert = OneLogin::RubySaml::Utils.format_cert(idp_cert)
|
208
|
-
certs[
|
204
|
+
certs[type].push(OpenSSL::X509::Certificate.new(formatted_cert))
|
209
205
|
end
|
210
206
|
end
|
211
207
|
|
@@ -247,7 +243,6 @@ module OneLogin
|
|
247
243
|
OpenSSL::PKey::RSA.new(formatted_private_key)
|
248
244
|
end
|
249
245
|
|
250
|
-
private
|
251
246
|
|
252
247
|
def idp_binding_from_embed_sign
|
253
248
|
security[:embed_sign] ? Utils::BINDINGS[:post] : Utils::BINDINGS[:redirect]
|
@@ -280,7 +275,9 @@ module OneLogin
|
|
280
275
|
:digest_method => XMLSecurity::Document::SHA1,
|
281
276
|
:signature_method => XMLSecurity::Document::RSA_SHA1,
|
282
277
|
:check_idp_cert_expiration => false,
|
283
|
-
:check_sp_cert_expiration => false
|
278
|
+
:check_sp_cert_expiration => false,
|
279
|
+
:strict_audience_validation => false,
|
280
|
+
:lowercase_url_encoding => false
|
284
281
|
}.freeze
|
285
282
|
}.freeze
|
286
283
|
end
|
@@ -248,32 +248,8 @@ module OneLogin
|
|
248
248
|
return true unless options.has_key? :get_params
|
249
249
|
return true unless options[:get_params].has_key? 'Signature'
|
250
250
|
|
251
|
-
|
252
|
-
# of URI-encoded values _as sent by the IDP_:
|
253
|
-
#
|
254
|
-
# > Further, note that URL-encoding is not canonical; that is, there are multiple legal encodings for a given
|
255
|
-
# > value. The relying party MUST therefore perform the verification step using the original URL-encoded
|
256
|
-
# > values it received on the query string. It is not sufficient to re-encode the parameters after they have been
|
257
|
-
# > processed by software because the resulting encoding may not match the signer's encoding.
|
258
|
-
#
|
259
|
-
# <http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf>
|
260
|
-
#
|
261
|
-
# If we don't have the original parts (for backward compatibility) required to correctly verify the signature,
|
262
|
-
# then fabricate them by re-encoding the parsed URI parameters, and hope that we're lucky enough to use
|
263
|
-
# the exact same URI-encoding as the IDP. (This is not the case if the IDP is ADFS!)
|
264
|
-
options[:raw_get_params] ||= {}
|
265
|
-
if options[:raw_get_params]['SAMLRequest'].nil? && !options[:get_params]['SAMLRequest'].nil?
|
266
|
-
options[:raw_get_params]['SAMLRequest'] = CGI.escape(options[:get_params]['SAMLRequest'])
|
267
|
-
end
|
268
|
-
if options[:raw_get_params]['RelayState'].nil? && !options[:get_params]['RelayState'].nil?
|
269
|
-
options[:raw_get_params]['RelayState'] = CGI.escape(options[:get_params]['RelayState'])
|
270
|
-
end
|
271
|
-
if options[:raw_get_params]['SigAlg'].nil? && !options[:get_params]['SigAlg'].nil?
|
272
|
-
options[:raw_get_params]['SigAlg'] = CGI.escape(options[:get_params]['SigAlg'])
|
273
|
-
end
|
251
|
+
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params], settings.security[:lowercase_url_encoding])
|
274
252
|
|
275
|
-
# If we only received the raw version of SigAlg,
|
276
|
-
# then parse it back into the decoded params hash for convenience.
|
277
253
|
if options[:get_params]['SigAlg'].nil? && !options[:raw_get_params]['SigAlg'].nil?
|
278
254
|
options[:get_params]['SigAlg'] = CGI.unescape(options[:raw_get_params]['SigAlg'])
|
279
255
|
end
|
@@ -335,7 +311,6 @@ module OneLogin
|
|
335
311
|
|
336
312
|
true
|
337
313
|
end
|
338
|
-
|
339
314
|
end
|
340
315
|
end
|
341
316
|
end
|
@@ -13,7 +13,7 @@ module OneLogin
|
|
13
13
|
class SloLogoutresponse < SamlMessage
|
14
14
|
|
15
15
|
# Logout Response ID
|
16
|
-
|
16
|
+
attr_accessor :uuid
|
17
17
|
|
18
18
|
# Initializes the Logout Response. A SloLogoutresponse Object that is an extension of the SamlMessage class.
|
19
19
|
# Asigns an ID, a random uuid.
|
@@ -41,7 +41,7 @@ module OneLogin
|
|
41
41
|
saml_response = CGI.escape(params.delete("SAMLResponse"))
|
42
42
|
response_params = "#{params_prefix}SAMLResponse=#{saml_response}"
|
43
43
|
params.each_pair do |key, value|
|
44
|
-
response_params << "&#{key
|
44
|
+
response_params << "&#{key}=#{CGI.escape(value.to_s)}"
|
45
45
|
end
|
46
46
|
|
47
47
|
raise SettingError.new "Invalid settings, idp_slo_service_url is not set!" if url.nil? or url.empty?
|
@@ -32,6 +32,7 @@ module OneLogin
|
|
32
32
|
(\d+)W # 8: Weeks
|
33
33
|
)
|
34
34
|
$)x.freeze
|
35
|
+
UUID_PREFIX = '_'
|
35
36
|
|
36
37
|
# Checks if the x509 cert provided is expired
|
37
38
|
#
|
@@ -166,27 +167,36 @@ module OneLogin
|
|
166
167
|
#
|
167
168
|
# @param rawparams [Hash] Raw GET Parameters
|
168
169
|
# @param params [Hash] GET Parameters
|
170
|
+
# @param lowercase_url_encoding [bool] Lowercase URL Encoding (For ADFS urlencode compatiblity)
|
169
171
|
# @return [Hash] New raw parameters
|
170
172
|
#
|
171
|
-
def self.prepare_raw_get_params(rawparams, params)
|
173
|
+
def self.prepare_raw_get_params(rawparams, params, lowercase_url_encoding=false)
|
172
174
|
rawparams ||= {}
|
173
175
|
|
174
176
|
if rawparams['SAMLRequest'].nil? && !params['SAMLRequest'].nil?
|
175
|
-
rawparams['SAMLRequest'] =
|
177
|
+
rawparams['SAMLRequest'] = escape_request_param(params['SAMLRequest'], lowercase_url_encoding)
|
176
178
|
end
|
177
179
|
if rawparams['SAMLResponse'].nil? && !params['SAMLResponse'].nil?
|
178
|
-
rawparams['SAMLResponse'] =
|
180
|
+
rawparams['SAMLResponse'] = escape_request_param(params['SAMLResponse'], lowercase_url_encoding)
|
179
181
|
end
|
180
182
|
if rawparams['RelayState'].nil? && !params['RelayState'].nil?
|
181
|
-
rawparams['RelayState'] =
|
183
|
+
rawparams['RelayState'] = escape_request_param(params['RelayState'], lowercase_url_encoding)
|
182
184
|
end
|
183
185
|
if rawparams['SigAlg'].nil? && !params['SigAlg'].nil?
|
184
|
-
rawparams['SigAlg'] =
|
186
|
+
rawparams['SigAlg'] = escape_request_param(params['SigAlg'], lowercase_url_encoding)
|
185
187
|
end
|
186
188
|
|
187
189
|
rawparams
|
188
190
|
end
|
189
191
|
|
192
|
+
def self.escape_request_param(param, lowercase_url_encoding)
|
193
|
+
CGI.escape(param).tap do |escaped|
|
194
|
+
next unless lowercase_url_encoding
|
195
|
+
|
196
|
+
escaped.gsub!(/%[A-Fa-f0-9]{2}/) { |match| match.downcase }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
190
200
|
# Validate the Signature parameter sent on the HTTP-Redirect binding
|
191
201
|
# @param params [Hash] Parameters to be used in the validation process
|
192
202
|
# @option params [OpenSSL::X509::Certificate] cert The Identity provider public certtificate
|
@@ -333,8 +343,12 @@ module OneLogin
|
|
333
343
|
end
|
334
344
|
end
|
335
345
|
|
346
|
+
def self.set_prefix(value)
|
347
|
+
UUID_PREFIX.replace value
|
348
|
+
end
|
349
|
+
|
336
350
|
def self.uuid
|
337
|
-
RUBY_VERSION < '1.9' ? "
|
351
|
+
"#{UUID_PREFIX}" + (RUBY_VERSION < '1.9' ? "#{@@uuid_generator.generate}" : "#{SecureRandom.uuid}")
|
338
352
|
end
|
339
353
|
|
340
354
|
# Given two strings, attempt to match them as URIs using Rails' parse method. If they can be parsed,
|
data/lib/xml_security.rb
CHANGED
@@ -177,7 +177,7 @@ module XMLSecurity
|
|
177
177
|
|
178
178
|
def compute_digest(document, digest_algorithm)
|
179
179
|
digest = digest_algorithm.digest(document)
|
180
|
-
Base64.encode64(digest).strip
|
180
|
+
Base64.encode64(digest).strip
|
181
181
|
end
|
182
182
|
|
183
183
|
end
|
@@ -216,7 +216,7 @@ module XMLSecurity
|
|
216
216
|
if options[:fingerprint_alg]
|
217
217
|
fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(options[:fingerprint_alg]).new
|
218
218
|
else
|
219
|
-
fingerprint_alg = OpenSSL::Digest
|
219
|
+
fingerprint_alg = OpenSSL::Digest.new('SHA1')
|
220
220
|
end
|
221
221
|
fingerprint = fingerprint_alg.hexdigest(cert.to_der)
|
222
222
|
|
data/ruby-saml.gemspec
CHANGED
@@ -6,17 +6,17 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.version = OneLogin::RubySaml::VERSION
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
-
s.authors = ["
|
9
|
+
s.authors = ["SAML Toolkit", "Sixto Martin"]
|
10
|
+
s.email = ['contact@iamdigitalservices.com', 'sixto.martin.garcia@gmail.com']
|
10
11
|
s.date = Time.now.strftime("%Y-%m-%d")
|
11
|
-
s.description = %q{SAML toolkit
|
12
|
-
s.email = %q{support@onelogin.com}
|
12
|
+
s.description = %q{SAML Ruby toolkit. Add SAML support to your Ruby software using this library}
|
13
13
|
s.license = 'MIT'
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
16
16
|
"README.md"
|
17
17
|
]
|
18
18
|
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
19
|
-
s.homepage = %q{https://github.com/
|
19
|
+
s.homepage = %q{https://github.com/saml-toolkit/ruby-saml}
|
20
20
|
s.rdoc_options = ["--charset=UTF-8"]
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
s.rubygems_version = %q{1.3.7}
|
@@ -27,12 +27,18 @@ Gem::Specification.new do |s|
|
|
27
27
|
# Nokogiri's version dependent on the Ruby version, even though we would
|
28
28
|
# have liked to constrain Ruby 1.8.7 to install only the 1.5.x versions.
|
29
29
|
if defined?(JRUBY_VERSION)
|
30
|
-
if JRUBY_VERSION < '9.
|
30
|
+
if JRUBY_VERSION < '9.1.7.0'
|
31
31
|
s.add_runtime_dependency('nokogiri', '>= 1.8.2', '<= 1.8.5')
|
32
32
|
s.add_runtime_dependency('jruby-openssl', '>= 0.9.8')
|
33
33
|
s.add_runtime_dependency('json', '< 2.3.0')
|
34
|
+
elsif JRUBY_VERSION < '9.2.0.0'
|
35
|
+
s.add_runtime_dependency('nokogiri', '>= 1.9.1', '< 1.10.0')
|
36
|
+
elsif JRUBY_VERSION < '9.3.2.0'
|
37
|
+
s.add_runtime_dependency('nokogiri', '>= 1.11.4')
|
38
|
+
s.add_runtime_dependency('rexml')
|
34
39
|
else
|
35
|
-
s.add_runtime_dependency('nokogiri', '>= 1.
|
40
|
+
s.add_runtime_dependency('nokogiri', '>= 1.13.10')
|
41
|
+
s.add_runtime_dependency('rexml')
|
36
42
|
end
|
37
43
|
elsif RUBY_VERSION < '1.9'
|
38
44
|
s.add_runtime_dependency('uuid')
|
@@ -41,20 +47,42 @@ Gem::Specification.new do |s|
|
|
41
47
|
s.add_runtime_dependency('nokogiri', '>= 1.5.10', '<= 1.6.8.1')
|
42
48
|
s.add_runtime_dependency('json', '< 2.3.0')
|
43
49
|
elsif RUBY_VERSION < '2.3'
|
44
|
-
s.add_runtime_dependency('nokogiri', '>= 1.9.1', '
|
50
|
+
s.add_runtime_dependency('nokogiri', '>= 1.9.1', '< 1.10.0')
|
51
|
+
elsif RUBY_VERSION < '2.5'
|
52
|
+
s.add_runtime_dependency('nokogiri', '>= 1.10.10', '< 1.11.0')
|
53
|
+
s.add_runtime_dependency('rexml')
|
54
|
+
elsif RUBY_VERSION < '2.6'
|
55
|
+
s.add_runtime_dependency('nokogiri', '>= 1.11.4')
|
56
|
+
s.add_runtime_dependency('rexml')
|
45
57
|
else
|
46
|
-
s.add_runtime_dependency('nokogiri', '>= 1.10
|
58
|
+
s.add_runtime_dependency('nokogiri', '>= 1.13.10')
|
47
59
|
s.add_runtime_dependency('rexml')
|
48
60
|
end
|
49
61
|
|
50
|
-
s.add_development_dependency('
|
62
|
+
s.add_development_dependency('simplecov', '<0.22.0')
|
63
|
+
if RUBY_VERSION < '2.4.1'
|
64
|
+
s.add_development_dependency('simplecov-lcov', '<0.8.0')
|
65
|
+
else
|
66
|
+
s.add_development_dependency('simplecov-lcov', '>0.7.0')
|
67
|
+
end
|
68
|
+
|
51
69
|
s.add_development_dependency('minitest', '~> 5.5')
|
52
70
|
s.add_development_dependency('mocha', '~> 0.14')
|
53
|
-
|
71
|
+
|
72
|
+
if RUBY_VERSION < '2.0'
|
73
|
+
s.add_development_dependency('rake', '~> 10')
|
74
|
+
else
|
75
|
+
s.add_development_dependency('rake', '>= 12.3.3')
|
76
|
+
end
|
77
|
+
|
54
78
|
s.add_development_dependency('shoulda', '~> 2.11')
|
55
|
-
s.add_development_dependency('simplecov')
|
56
79
|
s.add_development_dependency('systemu', '~> 2')
|
57
|
-
|
80
|
+
|
81
|
+
if RUBY_VERSION < '2.1'
|
82
|
+
s.add_development_dependency('timecop', '<= 0.6.0')
|
83
|
+
else
|
84
|
+
s.add_development_dependency('timecop', '~> 0.9')
|
85
|
+
end
|
58
86
|
|
59
87
|
if defined?(JRUBY_VERSION)
|
60
88
|
# All recent versions of JRuby play well with pry
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-saml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
|
7
|
+
- SAML Toolkit
|
8
|
+
- Sixto Martin
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2023-01-04 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: nokogiri
|
@@ -16,14 +17,14 @@ dependencies:
|
|
16
17
|
requirements:
|
17
18
|
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.10
|
20
|
+
version: 1.13.10
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
25
|
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.10
|
27
|
+
version: 1.13.10
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: rexml
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,19 +40,33 @@ dependencies:
|
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '0'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
43
|
+
name: simplecov
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
44
45
|
requirements:
|
45
|
-
- - "
|
46
|
+
- - "<"
|
46
47
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
48
|
+
version: 0.22.0
|
48
49
|
type: :development
|
49
50
|
prerelease: false
|
50
51
|
version_requirements: !ruby/object:Gem::Requirement
|
51
52
|
requirements:
|
52
|
-
- - "
|
53
|
+
- - "<"
|
53
54
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
55
|
+
version: 0.22.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: simplecov-lcov
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.7.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.7.0
|
55
70
|
- !ruby/object:Gem::Dependency
|
56
71
|
name: minitest
|
57
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +99,16 @@ dependencies:
|
|
84
99
|
name: rake
|
85
100
|
requirement: !ruby/object:Gem::Requirement
|
86
101
|
requirements:
|
87
|
-
- - "
|
102
|
+
- - ">="
|
88
103
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
104
|
+
version: 12.3.3
|
90
105
|
type: :development
|
91
106
|
prerelease: false
|
92
107
|
version_requirements: !ruby/object:Gem::Requirement
|
93
108
|
requirements:
|
94
|
-
- - "
|
109
|
+
- - ">="
|
95
110
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
111
|
+
version: 12.3.3
|
97
112
|
- !ruby/object:Gem::Dependency
|
98
113
|
name: shoulda
|
99
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,20 +123,6 @@ dependencies:
|
|
108
123
|
- - "~>"
|
109
124
|
- !ruby/object:Gem::Version
|
110
125
|
version: '2.11'
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: simplecov
|
113
|
-
requirement: !ruby/object:Gem::Requirement
|
114
|
-
requirements:
|
115
|
-
- - ">="
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
requirements:
|
122
|
-
- - ">="
|
123
|
-
- !ruby/object:Gem::Version
|
124
|
-
version: '0'
|
125
126
|
- !ruby/object:Gem::Dependency
|
126
127
|
name: systemu
|
127
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,16 +141,16 @@ dependencies:
|
|
140
141
|
name: timecop
|
141
142
|
requirement: !ruby/object:Gem::Requirement
|
142
143
|
requirements:
|
143
|
-
- - "
|
144
|
+
- - "~>"
|
144
145
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
146
|
+
version: '0.9'
|
146
147
|
type: :development
|
147
148
|
prerelease: false
|
148
149
|
version_requirements: !ruby/object:Gem::Requirement
|
149
150
|
requirements:
|
150
|
-
- - "
|
151
|
+
- - "~>"
|
151
152
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
153
|
+
version: '0.9'
|
153
154
|
- !ruby/object:Gem::Dependency
|
154
155
|
name: pry-byebug
|
155
156
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,8 +165,11 @@ dependencies:
|
|
164
165
|
- - ">="
|
165
166
|
- !ruby/object:Gem::Version
|
166
167
|
version: '0'
|
167
|
-
description: SAML toolkit
|
168
|
-
|
168
|
+
description: SAML Ruby toolkit. Add SAML support to your Ruby software using this
|
169
|
+
library
|
170
|
+
email:
|
171
|
+
- contact@iamdigitalservices.com
|
172
|
+
- sixto.martin.garcia@gmail.com
|
169
173
|
executables: []
|
170
174
|
extensions: []
|
171
175
|
extra_rdoc_files:
|
@@ -217,11 +221,11 @@ files:
|
|
217
221
|
- lib/schemas/xmldsig-core-schema.xsd
|
218
222
|
- lib/xml_security.rb
|
219
223
|
- ruby-saml.gemspec
|
220
|
-
homepage: https://github.com/
|
224
|
+
homepage: https://github.com/saml-toolkit/ruby-saml
|
221
225
|
licenses:
|
222
226
|
- MIT
|
223
227
|
metadata: {}
|
224
|
-
post_install_message:
|
228
|
+
post_install_message:
|
225
229
|
rdoc_options:
|
226
230
|
- "--charset=UTF-8"
|
227
231
|
require_paths:
|
@@ -237,9 +241,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
237
241
|
- !ruby/object:Gem::Version
|
238
242
|
version: '0'
|
239
243
|
requirements: []
|
240
|
-
|
241
|
-
|
242
|
-
signing_key:
|
244
|
+
rubygems_version: 3.3.26
|
245
|
+
signing_key:
|
243
246
|
specification_version: 4
|
244
247
|
summary: SAML Ruby Tookit
|
245
248
|
test_files: []
|