ruby-saml 1.16.0 → 1.18.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3094dc9c1e3692dddfc40adc2a4c305fae0be74bcd28b296f231ece4fe89334
4
- data.tar.gz: 1f47dcbd970af95d58049bdd7f8bfed6a5bf8a72a90c1938b2b8ef2a0d5dd05f
3
+ metadata.gz: 59cce47afe1159fc5674f2eaf8f0392d12df280cc97fa2a4ccd7926daf989445
4
+ data.tar.gz: 30a49c237e7a88328745b788d62e9ea92e87342fc571d20e002eb4feddd964ae
5
5
  SHA512:
6
- metadata.gz: 52ea3c1013e7b42b2e30c42bfbfd38bee0457d7bd630df94fcb9e9bc7db126e6981308af877a9b4c475e563a10159a0612d38d79458f289341730a496adeb77a
7
- data.tar.gz: e85c81f6fb8610793707c70c6dee09b4fe2053f307a7a2827df08038bc54b6250b77dfa3cf30d33d0029899aff1b82740347292df691a5e8757c3966058e842b
6
+ metadata.gz: c67ec4923ca4bc5e07736717d1e40f604296c95c00d1fe8ec7d28c586988b368d566a16782c676c2ce27d38d6d7e1386a5347bfbb40efc98eb033525605f5dcb
7
+ data.tar.gz: 4944ad0dc2a3999e78da570aa8faa6282e26868606a5011d2b623a6ef0a9150d2e6ee08a4245d090e5d4837a9dc9ffaa78bf46d84fe466ea9384662d305d4c94
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: [SAML-Toolkits]
@@ -8,11 +8,57 @@ jobs:
8
8
  strategy:
9
9
  fail-fast: false
10
10
  matrix:
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]
11
+ os:
12
+ - ubuntu-20.04
13
+ - macos-latest
14
+ - windows-latest
15
+ ruby-version:
16
+ - 2.1
17
+ - 2.2
18
+ - 2.3
19
+ - 2.4
20
+ - 2.5
21
+ - 2.6
22
+ - 2.7
23
+ - 3.0
24
+ - 3.1
25
+ - 3.2
26
+ - 3.3
27
+ - jruby-9.1
28
+ - jruby-9.2
29
+ - jruby-9.3
30
+ - jruby-9.4
31
+ - truffleruby
32
+ exclude:
33
+ - os: macos-latest
34
+ ruby-version: 2.1
35
+ - os: macos-latest
36
+ ruby-version: 2.2
37
+ - os: macos-latest
38
+ ruby-version: 2.3
39
+ - os: macos-latest
40
+ ruby-version: 2.4
41
+ - os: macos-latest
42
+ ruby-version: 2.5
43
+ - os: macos-latest
44
+ ruby-version: jruby-9.1
45
+ - os: macos-latest
46
+ ruby-version: jruby-9.2
47
+ - os: windows-latest
48
+ ruby-version: 2.1
49
+ - os: windows-latest
50
+ ruby-version: jruby-9.1
51
+ - os: windows-latest
52
+ ruby-version: jruby-9.2
53
+ - os: windows-latest
54
+ ruby-version: jruby-9.3
55
+ - os: windows-latest
56
+ ruby-version: jruby-9.4
57
+ - os: windows-latest
58
+ ruby-version: truffleruby
13
59
  runs-on: ${{ matrix.os }}
14
60
  steps:
15
- - uses: actions/checkout@v2
61
+ - uses: actions/checkout@v4
16
62
  - name: Set up Ruby ${{ matrix.ruby-version }}
17
63
  uses: ruby/setup-ruby@v1
18
64
  with:
data/CHANGELOG.md CHANGED
@@ -1,11 +1,28 @@
1
1
  # Ruby SAML Changelog
2
+
3
+ ### 1.18.0 (Mar 12, 2025)
4
+ * [#750](https://github.com/SAML-Toolkits/ruby-saml/pull/750) Fix vulnerabilities: CVE-2025-25291, CVE-2025-25292: SAML authentication bypass via Signature Wrapping attack allowed due parser differential. Fix vulnerability: CVE-2025-25293: Potential DOS abusing of compressed messages.
5
+ * [#718](https://github.com/SAML-Toolkits/ruby-saml/pull/718/) Add support to retrieve from SAMLResponse the AuthnInstant and AuthnContextClassRef values
6
+ * [#720](https://github.com/SAML-Toolkits/ruby-saml/pull/720) Fix ambiguous regex warnings
7
+ * [#715](https://github.com/SAML-Toolkits/ruby-saml/pull/715) Fix typo in SPNameQualifier error text
8
+
9
+ ### 1.17.0 (Sep 10, 2024)
10
+ * Fix for critical vulnerability CVE-2024-45409: SAML authentication bypass via Incorrect XPath selector
11
+ * [#687](https://github.com/SAML-Toolkits/ruby-saml/pull/687) Add CI coverage for Ruby 3.3 and Windows.
12
+ * [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) Add `Settings#sp_cert_multi` paramter to facilitate SP certificate and key rotation.
13
+ * [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) Support multiple simultaneous SP decryption keys via `Settings#sp_cert_multi` parameter.
14
+ * [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) Deprecate `Settings#certificate_new` parameter.
15
+ * [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) `:check_sp_cert_expiration` will use the first non-expired certificate/key when signing/decrypting. It will raise an error only if there are no valid certificates/keys.
16
+ * [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) `:check_sp_cert_expiration` now validates the certificate `not_before` condition; previously it was only validating `not_after`.
17
+ * [#673](https://github.com/SAML-Toolkits/ruby-saml/pull/673) `:check_sp_cert_expiration` now causes the generated SP metadata to exclude any inactive/expired certificates.
18
+
2
19
  ### 1.16.0 (Oct 09, 2023)
3
20
  * [#671](https://github.com/SAML-Toolkits/ruby-saml/pull/671) Add support on LogoutRequest with Encrypted NameID
4
21
 
5
22
  ### 1.15.0 (Jan 04, 2023)
6
23
  * [#650](https://github.com/SAML-Toolkits/ruby-saml/pull/650) Replace strip! by strip on compute_digest method
7
- * [#638](https://github.com/SAML-Toolkits/ruby-saml/pull/638) Fix dateTime format for the validUntil attribute of the generated metadata
8
- * [#576](https://github.com/SAML-Toolkits/ruby-saml/pull/576) Support idp cert multi with string keys
24
+ * [#638](https://github.com/SAML-Toolkits/ruby-saml/pull/638) Fix dateTime format for the validUntil attribute of the generated metadata
25
+ * [#576](https://github.com/SAML-Toolkits/ruby-saml/pull/576) Support `Settings#idp_cert_multi` with string keys
9
26
  * [#567](https://github.com/SAML-Toolkits/ruby-saml/pull/567) Improve Code quality
10
27
  * Add info about new repo, new maintainer, new security contact
11
28
  * Fix tests, Adjust dependencies, Add ruby 3.2 and new jruby versions tests to the CI. Add coveralls support
@@ -29,6 +46,12 @@
29
46
  * Add warning about the use of IdpMetadataParser class and SSRF
30
47
  * CI: Migrate from Travis to Github Actions
31
48
 
49
+ ### 1.12.4 (Mar 12, 2025)
50
+ * [#750](https://github.com/SAML-Toolkits/ruby-saml/pull/750) Fix vulnerabilities: CVE-2025-25291, CVE-2025-25292: SAML authentication bypass via Signature Wrapping attack allowed due parser differential. Fix vulnerability: CVE-2025-25293: Potential DOS abusing of compressed messages.
51
+
52
+ ### 1.12.3 (Sep 10, 2024)
53
+ * Fix for critical vulnerability CVE-2024-45409: SAML authentication bypass via Incorrect XPath selector
54
+
32
55
  ### 1.12.2 (Apr 08, 2021)
33
56
  * [#575](https://github.com/onelogin/ruby-saml/pull/575) Fix SloLogoutresponse bug on LogoutRequest
34
57
 
@@ -38,7 +61,7 @@
38
61
 
39
62
  ### 1.12.0 (Feb 18, 2021)
40
63
  * Support AES-128-GCM, AES-192-GCM, and AES-256-GCM encryptions
41
- * Parse & return SLO ResponseLocation in IDPMetadataParser & Settings
64
+ * Parse & return SLO ResponseLocation in IDPMetadataParser & Settings
42
65
  * Adding idp_sso_service_url and idp_slo_service_url settings
43
66
  * [#536](https://github.com/onelogin/ruby-saml/pull/536) Adding feth method to be able retrieve attributes based on regex
44
67
  * Reduce size of built gem by excluding the test folder
@@ -170,7 +193,7 @@
170
193
  * Fix response_test.rb of gem 1.3.0
171
194
  * Add reference to Security Guidelines
172
195
  * Update License
173
- * [#334](https://github.com/onelogin/ruby-saml/pull/334) Keep API backward-compatibility on IdpMetadataParser fingerprint method.
196
+ * [#334](https://github.com/onelogin/ruby-saml/pull/334) Keep API backward-compatibility on IdpMetadataParser fingerprint method.
174
197
 
175
198
  ### 1.3.0 (June 24, 2016)
176
199
  * [Security Fix](https://github.com/onelogin/ruby-saml/commit/a571f52171e6bfd87db59822d1d9e8c38fb3b995) Add extra validations to prevent Signature wrapping attacks
@@ -188,7 +211,7 @@
188
211
  * [#316](https://github.com/onelogin/ruby-saml/pull/316) Fix Misspelling of transation_id to transaction_id
189
212
  * [#321](https://github.com/onelogin/ruby-saml/pull/321) Support Attribute Names on IDPSSODescriptor parser
190
213
  * Changes on empty URI of Signature reference management
191
- * [#320](https://github.com/onelogin/ruby-saml/pull/320) Dont mutate document to fix lack of reference URI
214
+ * [#320](https://github.com/onelogin/ruby-saml/pull/320) Dont mutate document to fix lack of reference URI
192
215
  * [#306](https://github.com/onelogin/ruby-saml/pull/306) Support WantAssertionsSigned
193
216
 
194
217
  ### 1.1.2 (February 15, 2016)
@@ -205,9 +228,9 @@
205
228
  * [#270](https://github.com/onelogin/ruby-saml/pull/270) Allow SAML elements to come from any namespace (at decryption process)
206
229
  * [#261](https://github.com/onelogin/ruby-saml/pull/261) Allow validate_subject_confirmation Response validation to be skipped
207
230
  * [#258](https://github.com/onelogin/ruby-saml/pull/258) Fix allowed_clock_drift on the validate_session_expiration test
208
- * [#256](https://github.com/onelogin/ruby-saml/pull/256) Separate the create_authentication_xml_doc in two methods.
231
+ * [#256](https://github.com/onelogin/ruby-saml/pull/256) Separate the create_authentication_xml_doc in two methods.
209
232
  * [#255](https://github.com/onelogin/ruby-saml/pull/255) Refactor validate signature.
210
- * [#254](https://github.com/onelogin/ruby-saml/pull/254) Handle empty URI references
233
+ * [#254](https://github.com/onelogin/ruby-saml/pull/254) Handle empty URI references
211
234
  * [#251](https://github.com/onelogin/ruby-saml/pull/251) Support qualified and unqualified NameID in attributes
212
235
  * [#234](https://github.com/onelogin/ruby-saml/pull/234) Add explicit support for JRuby
213
236
 
@@ -215,7 +238,7 @@
215
238
  * [#247](https://github.com/onelogin/ruby-saml/pull/247) Avoid entity expansion (XEE attacks)
216
239
  * [#246](https://github.com/onelogin/ruby-saml/pull/246) Fix bug generating Logout Response (issuer was at wrong order)
217
240
  * [#243](https://github.com/onelogin/ruby-saml/issues/243) and [#244](https://github.com/onelogin/ruby-saml/issues/244) Fix metadata builder errors. Fix metadata xsd.
218
- * [#241](https://github.com/onelogin/ruby-saml/pull/241) Add decrypt support (EncryptID and EncryptedAssertion). Improve compatibility with namespaces.
241
+ * [#241](https://github.com/onelogin/ruby-saml/pull/241) Add decrypt support (EncryptID and EncryptedAssertion). Improve compatibility with namespaces.
219
242
  * [#240](https://github.com/onelogin/ruby-saml/pull/240) and [#238](https://github.com/onelogin/ruby-saml/pull/238) Improve test coverage and refactor.
220
243
  * [#239](https://github.com/onelogin/ruby-saml/pull/239) Improve security: Add more validations to SAMLResponse, LogoutRequest and LogoutResponse. Refactor code and improve tests coverage.
221
244
  * [#237](https://github.com/onelogin/ruby-saml/pull/237) Don't pretty print metadata by default.
data/README.md CHANGED
@@ -4,16 +4,45 @@
4
4
  [![Rubygem Version](https://badge.fury.io/rb/ruby-saml.svg)](https://badge.fury.io/rb/ruby-saml)
5
5
  [![GitHub version](https://badge.fury.io/gh/SAML-Toolkits%2Fruby-saml.svg)](https://badge.fury.io/gh/SAML-Toolkits%2Fruby-saml) ![GitHub](https://img.shields.io/github/license/SAML-Toolkits/ruby-saml) ![Gem](https://img.shields.io/gem/dtv/ruby-saml?label=gem%20downloads%20latest) ![Gem](https://img.shields.io/gem/dt/ruby-saml?label=gem%20total%20downloads)
6
6
 
7
- Ruby SAML minor and tiny versions may introduce breaking changes. Please read
7
+ Minor and patch versions of Ruby SAML may introduce breaking changes. Please read
8
8
  [UPGRADING.md](UPGRADING.md) for guidance on upgrading to new Ruby SAML versions.
9
9
 
10
+ ### Pay it Forward: Support RubySAML and Strengthen Open-Source Security
11
+
12
+ RubySAML is a trusted authentication library used by startups and enterprises alike.
13
+
14
+ But security doesn't happen in a vacuum. Vulnerabilities in authentication libraries can
15
+ have widespread consequences. Maintaining open-source security requires continuous
16
+ effort, expertise, and funding. By supporting RubySAML, you’re not just securing your
17
+ own systems—you’re strengthening auth security globally.
18
+
19
+ #### How you can help
20
+
21
+ * Sponsor RubySAML: [GitHub Sponsors](https://github.com/sponsors/SAML-Toolkits)
22
+ * Contribute to secure-by-design improvements
23
+ * Responsibly report vulnerabilities (see "Vulnerability Reporting" above)
24
+
25
+ Security is a shared responsibility. If RubySAML has helped your organization, please
26
+ consider giving back. Together, we can keep authentication secure.
27
+
28
+ ### Sponsors
29
+
30
+ Thanks to the following sponsors for securing the open source ecosystem,
31
+
32
+ [<img alt="84codes" src="https://avatars.githubusercontent.com/u/5353257" width="75px">](https://www.84codes.com)
33
+
34
+
35
+ ## Vulnerabilities
36
+
37
+ There are critical vulnerabilities affecting ruby-saml < 1.18.0, two of them allows SAML authentication bypass (CVE-2025-25291, CVE-2025-25292, CVE-2025-25293). Please upgrade to a fixed version (1.18.0)
38
+
10
39
  ## Overview
11
40
 
12
41
  The Ruby SAML library is for implementing the client side of a SAML authorization,
13
42
  i.e. it provides a means for managing authorization initialization and confirmation
14
43
  requests from identity providers.
15
44
 
16
- SAML authorization is a two step process and you are expected to implement support for both.
45
+ SAML authorization is a two-step process and you are expected to implement support for both.
17
46
 
18
47
  We created a demo project for Rails 4 that uses the latest version of this library:
19
48
  [ruby-saml-example](https://github.com/saml-toolkits/ruby-saml-example)
@@ -22,37 +51,17 @@ We created a demo project for Rails 4 that uses the latest version of this libra
22
51
 
23
52
  The following Ruby versions are covered by CI testing:
24
53
 
25
- * 2.1.x
26
- * 2.2.x
27
- * 2.3.x
28
- * 2.4.x
29
- * 2.5.x
30
- * 2.6.x
31
- * 2.7.x
32
- * 3.0.x
33
- * 3.1
34
- * 3.2
35
- * JRuby 9.1.x
36
- * JRuby 9.2.x
37
- * JRuby 9.3.X
38
- * JRuby 9.4.0
54
+ * Ruby (MRI) 2.1 to 3.3
55
+ * JRuby 9.1 to 9.4
39
56
  * TruffleRuby (latest)
40
57
 
41
- In addition, the following may work but are untested:
42
-
43
- * 1.8.7
44
- * 1.9.x
45
- * 2.0.x
46
- * JRuby 1.7.x
47
- * JRuby 9.0.x
48
-
49
58
  ## Adding Features, Pull Requests
50
59
 
51
60
  * Fork the repository
52
61
  * Make your feature addition or bug fix
53
62
  * Add tests for your new features. This is important so we don't break any features in a future version unintentionally.
54
63
  * Ensure all tests pass by running `bundle exec rake test`.
55
- * Do not change rakefile, version, or history.
64
+ * Do not change Rakefile, version, or history.
56
65
  * Open a pull request, following [this template](https://gist.github.com/Lordnibbler/11002759).
57
66
 
58
67
  ## Security Guidelines
@@ -63,21 +72,20 @@ by mail to the maintainer: sixto.martin.garcia+security@gmail.com
63
72
  ### Security Warning
64
73
 
65
74
  Some tools may incorrectly report ruby-saml is a potential security vulnerability.
66
- ruby-saml depends on Nokogiri, and it's possible to use Nokogiri in a dangerous way
75
+ ruby-saml depends on Nokogiri, and it is possible to use Nokogiri in a dangerous way
67
76
  (by enabling its DTDLOAD option and disabling its NONET option).
68
77
  This dangerous Nokogiri configuration, which is sometimes used by other components,
69
78
  can create an XML External Entity (XXE) vulnerability if the XML data is not trusted.
70
79
  However, ruby-saml never enables this dangerous Nokogiri configuration;
71
80
  ruby-saml never enables DTDLOAD, and it never disables NONET.
72
81
 
73
- The OneLogin::RubySaml::IdpMetadataParser class does not validate in any way the URL
74
- that is introduced in order to be parsed.
82
+ The OneLogin::RubySaml::IdpMetadataParser class does not validate the provided URL before parsing.
75
83
 
76
- Usually the same administrator that handles the Service Provider also sets the URL to
84
+ Usually, the same administrator who handles the Service Provider also sets the URL to
77
85
  the IdP, which should be a trusted resource.
78
86
 
79
- But there are other scenarios, like a SAAS app where the administrator of the app
80
- delegates this functionality to other users. In this case, extra precaution should
87
+ But there are other scenarios, like a SaaS app where the administrator of the app
88
+ delegates this functionality to other users. In this case, extra precautions should
81
89
  be taken in order to validate such URL inputs and avoid attacks like SSRF.
82
90
 
83
91
  ## Getting Started
@@ -89,7 +97,7 @@ Using `Gemfile`
89
97
 
90
98
  ```ruby
91
99
  # latest stable
92
- gem 'ruby-saml', '~> 1.11.0'
100
+ gem 'ruby-saml', '~> 1.17.0'
93
101
 
94
102
  # or track master for bleeding-edge
95
103
  gem 'ruby-saml', :github => 'saml-toolkit/ruby-saml'
@@ -134,8 +142,8 @@ gem install nokogiri --version '~> 1.5.10'
134
142
  ### Configuring Logging
135
143
 
136
144
  When troubleshooting SAML integration issues, you will find it extremely helpful to examine the
137
- output of this gem's business logic. By default, log messages are emitted to RAILS_DEFAULT_LOGGER
138
- when the gem is used in a Rails context, and to STDOUT when the gem is used outside of Rails.
145
+ output of this gem's business logic. By default, log messages are emitted to `RAILS_DEFAULT_LOGGER`
146
+ when the gem is used in a Rails context, and to `STDOUT` when the gem is used outside of Rails.
139
147
 
140
148
  To override the default behavior and control the destination of log messages, provide
141
149
  a ruby Logger object to the gem's logging singleton:
@@ -158,7 +166,7 @@ def init
158
166
  end
159
167
  ```
160
168
 
161
- If the SP knows who should be authenticated in the IdP, then can provide that info as follows:
169
+ If the SP knows who should be authenticated in the IdP, it can provide that info as follows:
162
170
 
163
171
  ```ruby
164
172
  def init
@@ -236,7 +244,7 @@ def saml_settings
236
244
  end
237
245
  ```
238
246
 
239
- The use of settings.issuer is deprecated in favour of settings.sp_entity_id since version 1.11.0
247
+ The use of `settings.issuer` is deprecated in favor of `settings.sp_entity_id` since version 1.11.0
240
248
 
241
249
  Some assertion validations can be skipped by passing parameters to `OneLogin::RubySaml::Response.new()`.
242
250
  For example, you can skip the `AuthnStatement`, `Conditions`, `Recipient`, or the `SubjectConfirmation`
@@ -391,11 +399,11 @@ IdpMetadataParser by its Entity Id value:
391
399
  )
392
400
  ```
393
401
 
394
- ### Retrieve one Entity Descriptor with an specific binding and nameid format when several are available
402
+ ### Retrieve one Entity Descriptor with a specific binding and nameid format when several are available
395
403
 
396
- If the Metadata contains several bindings and nameids, the relevant ones
397
- also can be specified when retrieving the settings from the IdpMetadataParser
398
- by the values of binding and nameid:
404
+ If the metadata contains multiple bindings and NameID formats, the relevant ones
405
+ can be specified when retrieving the settings from the IdpMetadataParser
406
+ by the values of binding and NameID:
399
407
 
400
408
  ```ruby
401
409
  validate_cert = true
@@ -459,13 +467,13 @@ if valid
459
467
  entity_id: "<entity_id_of_the_entity_to_be_retrieved>"
460
468
  )
461
469
  else
462
- print "Metadata Signarture failed to be verified with the cert provided"
470
+ print "Metadata Signature failed to be verified with the cert provided"
463
471
  end
464
472
  ```
465
473
 
466
474
  ## Retrieving Attributes
467
475
 
468
- 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
476
+ If you are using `saml:AttributeStatement` to transfer data, such as 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
469
477
  `single_value_compatibility` (when activated, only the first value is returned)
470
478
 
471
479
  ```ruby
@@ -688,7 +696,7 @@ Next, you may specify the specific SP SAML messages you would like to sign:
688
696
  settings.security[:logout_responses_signed] = true # Enable signature on Logout Response
689
697
  ```
690
698
 
691
- Signatures will be handled automatically for both `HTTP-Redirect` and `HTTP-Redirect` Binding.
699
+ Signatures will be handled automatically for both `HTTP-Redirect` and `HTTP-POST` Binding.
692
700
  Note that the RelayState parameter is used when creating the Signature on the `HTTP-Redirect` Binding.
693
701
  Remember to provide it to the Signature builder if you are sending a `GET RelayState` parameter or the
694
702
  signature validation process will fail at the Identity Provider.
@@ -735,10 +743,52 @@ validation fails. You may disable such exceptions using the `settings.security[:
735
743
  settings.security[:soft] = true # Do not raise error on failed signature/certificate validations
736
744
  ```
737
745
 
746
+ #### Advanced SP Certificate Usage & Key Rollover
747
+
748
+ Ruby SAML provides the `settings.sp_cert_multi` parameter to enable the following
749
+ advanced usage scenarios:
750
+ - Rotating SP certificates and private keys without disruption of service.
751
+ - Specifying separate SP certificates for signing and encryption.
752
+
753
+ The `sp_cert_multi` parameter replaces `certificate` and `private_key`
754
+ (you may not specify both pparameters at the same time.) `sp_cert_multi` has the following shape:
755
+
756
+ ```ruby
757
+ settings.sp_cert_multi = {
758
+ signing: [
759
+ { certificate: cert1, private_key: private_key1 },
760
+ { certificate: cert2, private_key: private_key2 }
761
+ ],
762
+ encryption: [
763
+ { certificate: cert1, private_key: private_key1 },
764
+ { certificate: cert3, private_key: private_key1 }
765
+ ],
766
+ }
767
+ ```
768
+
769
+ Certificate rotation is acheived by inserting new certificates at the bottom of each list,
770
+ and then removing the old certificates from the top of the list once your IdPs have migrated.
771
+ A common practice is for apps to publish the current SP metadata at a URL endpoint and have
772
+ the IdP regularly poll for updates.
773
+
774
+ Note the following:
775
+ - You may re-use the same certificate and/or private key in multiple places, including for both signing and encryption.
776
+ - The IdP should attempt to verify signatures with *all* `:signing` certificates,
777
+ and permit if *any one* succeeds. When signing, Ruby SAML will use the first SP certificate
778
+ in the `sp_cert_multi[:signing]` array. This will be the first active/non-expired certificate
779
+ in the array if `settings.security[:check_sp_cert_expiration]` is true.
780
+ - The IdP may encrypt with any of the SP certificates in the `sp_cert_multi[:encryption]`
781
+ array. When decrypting, Ruby SAML attempt to decrypt with each SP private key in
782
+ `sp_cert_multi[:encryption]` until the decryption is successful. This will skip private
783
+ keys for inactive/expired certificates if `:check_sp_cert_expiration` is true.
784
+ - If `:check_sp_cert_expiration` is true, the generated SP metadata XML will not include
785
+ inactive/expired certificates. This avoids validation errors when the IdP reads the SP
786
+ metadata.
787
+
738
788
  #### Audience Validation
739
789
 
740
790
  A service provider should only consider a SAML response valid if the IdP includes an <AudienceRestriction>
741
- element containting an <Audience> element that uniquely identifies the service provider. Unless you specify
791
+ element containing an <Audience> element that uniquely identifies the service provider. Unless you specify
742
792
  the `skip_audience` option, Ruby SAML will validate that each SAML response includes an <Audience> element
743
793
  whose contents matches `settings.sp_entity_id`.
744
794
 
@@ -758,29 +808,6 @@ is invalid using the `settings.security[:strict_audience_validation]` parameter.
758
808
  settings.security[:strict_audience_validation] = true
759
809
  ```
760
810
 
761
- #### Key Rollover
762
-
763
- To update the SP X.509 certificate and private key without disruption of service, you may define the parameter
764
- `settings.certificate_new`. This will publish the new SP certificate in your metadata so that your IdP counterparties
765
- may cache it in preparation for rollover.
766
-
767
- For example, if you to rollover from `CERT A` to `CERT B`. Before rollover, your settings should look as follows.
768
- Both `CERT A` and `CERT B` will now appear in your SP metadata, however `CERT A` will still be used for signing
769
- and encryption at this time.
770
-
771
- ```ruby
772
- settings.certificate = "CERT A"
773
- settings.private_key = "PRIVATE KEY FOR CERT A"
774
- settings.certificate_new = "CERT B"
775
- ```
776
-
777
- After the IdP has cached `CERT B`, you may then change your settings as follows:
778
-
779
- ```ruby
780
- settings.certificate = "CERT B"
781
- settings.private_key = "PRIVATE KEY FOR CERT B"
782
- ```
783
-
784
811
  ## Single Log Out
785
812
 
786
813
  Ruby SAML supports SP-initiated Single Logout and IdP-Initiated Single Logout.
@@ -939,7 +966,7 @@ end
939
966
 
940
967
  ## Attribute Service
941
968
 
942
- To request attributes from the IdP the SP needs to provide an attribute service within it's metadata and reference the index in the assertion.
969
+ To request attributes from the IdP the SP must provide an attribute service within its metadata and reference the index in the assertion.
943
970
 
944
971
  ```ruby
945
972
  settings = OneLogin::RubySaml::Settings.new
@@ -956,7 +983,7 @@ The `attribute_value` option additionally accepts an array of possible values.
956
983
 
957
984
  ## Custom Metadata Fields
958
985
 
959
- Some IdPs may require to add SPs to add additional fields (Organization, ContactPerson, etc.)
986
+ Some IdPs may require SPs to add additional fields (Organization, ContactPerson, etc.)
960
987
  into the SP metadata. This can be achieved by extending the `OneLogin::RubySaml::Metadata`
961
988
  class and overriding the `#add_extras` method as per the following example:
962
989
 
data/UPGRADING.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Ruby SAML Migration Guide
2
2
 
3
+ ## Updating from 1.17.x to 1.18.0
4
+
5
+ Version `1.18.0` changes the way the toolkit validates SAML signatures. There is a new order
6
+ how validation happens in the toolkit and also the toolkit by default will check malformed doc
7
+ when parsing a SAML Message (`settings.check_malformed_doc`).
8
+
9
+ The SignedDocument class defined at xml_security.rb experienced several changes.
10
+ We don't expect compatibilty issues if you use the main methods offered by ruby-saml, but if you use a fork or customized usage, is possible that you need to adapt your code.
11
+
3
12
  ## Updating from 1.12.x to 1.13.0
4
13
 
5
14
  Version `1.13.0` adds `settings.idp_sso_service_binding` and `settings.idp_slo_service_binding`, and
@@ -64,7 +64,7 @@ module OneLogin
64
64
  request_doc = create_authentication_xml_doc(settings)
65
65
  request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
66
66
 
67
- request = ""
67
+ request = "".dup
68
68
  request_doc.write(request)
69
69
 
70
70
  Logging.debug "Created AuthnRequest: #{request}"
@@ -72,9 +72,10 @@ module OneLogin
72
72
  request = deflate(request) if settings.compress_request
73
73
  base64_request = encode(request)
74
74
  request_params = {"SAMLRequest" => base64_request}
75
+ sp_signing_key = settings.get_sp_signing_key
75
76
 
76
- if settings.idp_sso_service_binding == Utils::BINDINGS[:redirect] && settings.security[:authn_requests_signed] && settings.private_key
77
- params['SigAlg'] = settings.security[:signature_method]
77
+ if settings.idp_sso_service_binding == Utils::BINDINGS[:redirect] && settings.security[:authn_requests_signed] && sp_signing_key
78
+ params['SigAlg'] = settings.security[:signature_method]
78
79
  url_string = OneLogin::RubySaml::Utils.build_query(
79
80
  :type => 'SAMLRequest',
80
81
  :data => base64_request,
@@ -82,7 +83,7 @@ module OneLogin
82
83
  :sig_alg => params['SigAlg']
83
84
  )
84
85
  sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
85
- signature = settings.get_sp_key.sign(sign_algorithm.new, url_string)
86
+ signature = sp_signing_key.sign(sign_algorithm.new, url_string)
86
87
  params['Signature'] = encode(signature)
87
88
  end
88
89
 
@@ -179,15 +180,13 @@ module OneLogin
179
180
  end
180
181
 
181
182
  def sign_document(document, settings)
182
- if settings.idp_sso_service_binding == Utils::BINDINGS[:post] && settings.security[:authn_requests_signed] && settings.private_key && settings.certificate
183
- private_key = settings.get_sp_key
184
- cert = settings.get_sp_cert
183
+ cert, private_key = settings.get_sp_signing_pair
184
+ if settings.idp_sso_service_binding == Utils::BINDINGS[:post] && settings.security[:authn_requests_signed] && private_key && cert
185
185
  document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
186
186
  end
187
187
 
188
188
  document
189
189
  end
190
-
191
190
  end
192
191
  end
193
192
  end
@@ -186,8 +186,6 @@ module OneLogin
186
186
  idpsso_descriptors.map {|id| IdpMetadata.new(id, id.parent.attributes["entityID"])}
187
187
  end
188
188
 
189
- private
190
-
191
189
  # Retrieve the remote IdP metadata from the URL or a cached copy.
192
190
  # @param url [String] Url where the XML of the Identity Provider Metadata is published.
193
191
  # @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
@@ -220,6 +218,8 @@ module OneLogin
220
218
  )
221
219
  end
222
220
 
221
+ private
222
+
223
223
  class IdpMetadata
224
224
  attr_reader :idpsso_descriptor, :entity_id
225
225
 
@@ -384,14 +384,12 @@ module OneLogin
384
384
  # @return [String|nil] the fingerpint of the X509Certificate if it exists
385
385
  #
386
386
  def fingerprint(certificate, fingerprint_algorithm = XMLSecurity::Document::SHA1)
387
- @fingerprint ||= begin
388
- return unless certificate
387
+ return unless certificate
389
388
 
390
- cert = OpenSSL::X509::Certificate.new(Base64.decode64(certificate))
389
+ cert = OpenSSL::X509::Certificate.new(Base64.decode64(certificate))
391
390
 
392
- fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(fingerprint_algorithm).new
393
- fingerprint_alg.hexdigest(cert.to_der).upcase.scan(/../).join(":")
394
- end
391
+ fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(fingerprint_algorithm).new
392
+ fingerprint_alg.hexdigest(cert.to_der).upcase.scan(/../).join(":")
395
393
  end
396
394
 
397
395
  # @return [Array] the names of all SAML attributes if any exist
@@ -61,7 +61,7 @@ module OneLogin
61
61
  request_doc = create_logout_request_xml_doc(settings)
62
62
  request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
63
63
 
64
- request = ""
64
+ request = "".dup
65
65
  request_doc.write(request)
66
66
 
67
67
  Logging.debug "Created SLO Logout Request: #{request}"
@@ -69,8 +69,9 @@ module OneLogin
69
69
  request = deflate(request) if settings.compress_request
70
70
  base64_request = encode(request)
71
71
  request_params = {"SAMLRequest" => base64_request}
72
+ sp_signing_key = settings.get_sp_signing_key
72
73
 
73
- if settings.idp_slo_service_binding == Utils::BINDINGS[:redirect] && settings.security[:logout_requests_signed] && settings.private_key
74
+ if settings.idp_slo_service_binding == Utils::BINDINGS[:redirect] && settings.security[:logout_requests_signed] && sp_signing_key
74
75
  params['SigAlg'] = settings.security[:signature_method]
75
76
  url_string = OneLogin::RubySaml::Utils.build_query(
76
77
  :type => 'SAMLRequest',
@@ -79,7 +80,7 @@ module OneLogin
79
80
  :sig_alg => params['SigAlg']
80
81
  )
81
82
  sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
82
- signature = settings.get_sp_key.sign(sign_algorithm.new, url_string)
83
+ signature = settings.get_sp_signing_key.sign(sign_algorithm.new, url_string)
83
84
  params['Signature'] = encode(signature)
84
85
  end
85
86
 
@@ -138,9 +139,8 @@ module OneLogin
138
139
 
139
140
  def sign_document(document, settings)
140
141
  # embed signature
141
- if settings.idp_slo_service_binding == Utils::BINDINGS[:post] && settings.security[:logout_requests_signed] && settings.private_key && settings.certificate
142
- private_key = settings.get_sp_key
143
- cert = settings.get_sp_cert
142
+ cert, private_key = settings.get_sp_signing_pair
143
+ if settings.idp_slo_service_binding == Utils::BINDINGS[:post] && settings.security[:logout_requests_signed] && private_key && cert
144
144
  document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
145
145
  end
146
146
 
@@ -150,7 +150,8 @@ module OneLogin
150
150
  # @raise [ValidationError] if soft == false and validation fails
151
151
  #
152
152
  def validate_structure
153
- unless valid_saml?(document, soft)
153
+ check_malformed_doc = check_malformed_doc?(settings)
154
+ unless valid_saml?(document, soft, check_malformed_doc)
154
155
  return append_error("Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd")
155
156
  end
156
157