ruby-saml 1.12.4 → 1.13.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 +4 -44
- data/{changelog.md → CHANGELOG.md} +19 -12
- data/README.md +288 -226
- data/UPGRADING.md +149 -0
- data/lib/onelogin/ruby-saml/authrequest.rb +2 -3
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +110 -77
- data/lib/onelogin/ruby-saml/logoutrequest.rb +3 -3
- data/lib/onelogin/ruby-saml/logoutresponse.rb +2 -3
- data/lib/onelogin/ruby-saml/metadata.rb +59 -22
- data/lib/onelogin/ruby-saml/response.rb +16 -25
- data/lib/onelogin/ruby-saml/saml_message.rb +12 -24
- data/lib/onelogin/ruby-saml/settings.rb +76 -70
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +13 -6
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +2 -2
- data/lib/onelogin/ruby-saml/utils.rb +27 -22
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +25 -72
- data/ruby-saml.gemspec +1 -9
- metadata +23 -36
- data/.travis.yml +0 -48
data/UPGRADING.md
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
# Ruby SAML Migration Guide
|
2
|
+
|
3
|
+
## Updating from 1.12.x to 1.13.0 (NOT YET RELEASED)
|
4
|
+
|
5
|
+
Version `1.13.0` adds `settings.idp_sso_service_binding` and `settings.idp_slo_service_binding`, and
|
6
|
+
deprecates `settings.security[:embed_sign]`. If specified, new binding parameters will be used in place of `:embed_sign`
|
7
|
+
to determine how to handle SAML message signing (`HTTP-POST` embeds signature and `HTTP-Redirect` does not.)
|
8
|
+
|
9
|
+
In addition, the `IdpMetadataParser#parse`, `#parse_to_hash` and `#parse_to_array` methods now retrieve
|
10
|
+
`idp_sso_service_binding` and `idp_slo_service_binding`.
|
11
|
+
|
12
|
+
Lastly, for convenience you may now use the Symbol aliases `:post` and `:redirect` for any `settings.*_binding` parameter.
|
13
|
+
|
14
|
+
## Upgrading from 1.11.x to 1.12.0
|
15
|
+
|
16
|
+
Version `1.12.0` adds support for gcm algorithm and
|
17
|
+
change/adds specific error messages for signature validations
|
18
|
+
|
19
|
+
`idp_sso_target_url` and `idp_slo_target_url` attributes of the Settings class deprecated
|
20
|
+
in favor of `idp_sso_service_url` and `idp_slo_service_url`. The `IdpMetadataParser#parse`,
|
21
|
+
`#parse_to_hash` and `#parse_to_array` methods now retrieve SSO URL and SLO URL endpoints with
|
22
|
+
`idp_sso_service_url` and `idp_slo_service_url` (previously `idp_sso_target_url` and
|
23
|
+
`idp_slo_target_url` respectively).
|
24
|
+
|
25
|
+
## Upgrading from 1.10.x to 1.11.0
|
26
|
+
|
27
|
+
Version `1.11.0` deprecates the use of `settings.issuer` in favour of `settings.sp_entity_id`.
|
28
|
+
There are two new security settings: `settings.security[:check_idp_cert_expiration]` and
|
29
|
+
`settings.security[:check_sp_cert_expiration]` (both false by default) that check if the
|
30
|
+
IdP or SP X.509 certificate has expired, respectively.
|
31
|
+
|
32
|
+
Version `1.10.2` includes the `valid_until` attribute in parsed IdP metadata.
|
33
|
+
|
34
|
+
Version `1.10.1` improves Ruby 1.8.7 support.
|
35
|
+
|
36
|
+
## Upgrading from 1.9.0 to 1.10.0
|
37
|
+
|
38
|
+
Version `1.10.0` improves IdpMetadataParser to allow parse multiple IDPSSODescriptor,
|
39
|
+
Add Subject support on AuthNRequest to allow SPs provide info to the IdP about the user
|
40
|
+
to be authenticated and updates the format_cert method to accept certs with /\x0d/
|
41
|
+
|
42
|
+
## Upgrading from 1.8.0 to 1.9.0
|
43
|
+
|
44
|
+
Version `1.9.0` better supports Ruby 2.4+ and JRuby 9.2.0.0. `Settings` initialization
|
45
|
+
now has a second parameter, `keep_security_settings` (default: false), which saves security
|
46
|
+
settings attributes that are not explicitly overridden, if set to true.
|
47
|
+
|
48
|
+
## Upgrading from 1.7.x to 1.8.0
|
49
|
+
|
50
|
+
On Version `1.8.0`, creating AuthRequests/LogoutRequests/LogoutResponses with nil RelayState
|
51
|
+
param will not generate a URL with an empty RelayState parameter anymore. It also changes
|
52
|
+
the invalid audience error message.
|
53
|
+
|
54
|
+
## Upgrading from 1.6.0 to 1.7.0
|
55
|
+
|
56
|
+
Version `1.7.0` is a recommended update for all Ruby SAML users as it includes a fix for
|
57
|
+
the [CVE-2017-11428](https://www.cvedetails.com/cve/CVE-2017-11428/) vulnerability.
|
58
|
+
|
59
|
+
## Upgrading from 1.5.0 to 1.6.0
|
60
|
+
|
61
|
+
Version `1.6.0` changes the preferred way to construct instances of `Logoutresponse` and
|
62
|
+
`SloLogoutrequest`. Previously the _SAMLResponse_, _RelayState_, and _SigAlg_ parameters
|
63
|
+
of these message types were provided via the constructor's `options[:get_params]` parameter.
|
64
|
+
Unfortunately this can result in incompatibility with other SAML implementations; signatures
|
65
|
+
are specified to be computed based on the _sender's_ URI-encoding of the message, which can
|
66
|
+
differ from that of Ruby SAML. In particular, Ruby SAML's URI-encoding does not match that
|
67
|
+
of Microsoft ADFS, so messages from ADFS can fail signature validation.
|
68
|
+
|
69
|
+
The new preferred way to provide _SAMLResponse_, _RelayState_, and _SigAlg_ is via the
|
70
|
+
`options[:raw_get_params]` parameter. For example:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# In this example `query_params` is assumed to contain decoded query parameters,
|
74
|
+
# and `raw_query_params` is assumed to contain encoded query parameters as sent by the IDP.
|
75
|
+
settings = {
|
76
|
+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
77
|
+
settings.soft = false
|
78
|
+
}
|
79
|
+
options = {
|
80
|
+
get_params: {
|
81
|
+
"Signature" => query_params["Signature"],
|
82
|
+
},
|
83
|
+
raw_get_params: {
|
84
|
+
"SAMLRequest" => raw_query_params["SAMLRequest"],
|
85
|
+
"SigAlg" => raw_query_params["SigAlg"],
|
86
|
+
"RelayState" => raw_query_params["RelayState"],
|
87
|
+
},
|
88
|
+
}
|
89
|
+
slo_logout_request = OneLogin::RubySaml::SloLogoutrequest.new(query_params["SAMLRequest"], settings, options)
|
90
|
+
raise "Invalid Logout Request" unless slo_logout_request.is_valid?
|
91
|
+
```
|
92
|
+
|
93
|
+
The old form is still supported for backward compatibility, but all Ruby SAML users
|
94
|
+
should prefer `options[:raw_get_params]` where possible to ensure compatibility with
|
95
|
+
other SAML implementations.
|
96
|
+
|
97
|
+
## Upgrading from 1.4.2 to 1.4.3
|
98
|
+
|
99
|
+
Version `1.4.3` introduces Recipient validation of SubjectConfirmation elements.
|
100
|
+
The 'Recipient' value is compared with the settings.assertion_consumer_service_url
|
101
|
+
value.
|
102
|
+
|
103
|
+
If you want to skip that validation, add the :skip_recipient_check option to the
|
104
|
+
initialize method of the Response object.
|
105
|
+
|
106
|
+
Parsing metadata that contains more than one certificate will propagate the
|
107
|
+
idp_cert_multi property rather than idp_cert. See [signature validation
|
108
|
+
section](#signature-validation) for details.
|
109
|
+
|
110
|
+
## Upgrading from 1.3.x to 1.4.x
|
111
|
+
|
112
|
+
Version `1.4.0` is a recommended update for all Ruby SAML users as it includes security improvements.
|
113
|
+
|
114
|
+
## Upgrading from 1.2.x to 1.3.x
|
115
|
+
|
116
|
+
Version `1.3.0` is a recommended update for all Ruby SAML users as it includes security fixes.
|
117
|
+
It adds security improvements in order to prevent Signature wrapping attacks.
|
118
|
+
[CVE-2016-5697](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-5697)
|
119
|
+
|
120
|
+
## Upgrading from 1.1.x to 1.2.x
|
121
|
+
|
122
|
+
Version `1.2` adds IDP metadata parsing improvements, uuid deprecation in favour of SecureRandom,
|
123
|
+
refactor error handling and some minor improvements.
|
124
|
+
|
125
|
+
There is no compatibility issue detected.
|
126
|
+
|
127
|
+
For more details, please review [CHANGELOG.md](CHANGELOG.md).
|
128
|
+
|
129
|
+
## Upgrading from 1.0.x to 1.1.x
|
130
|
+
|
131
|
+
Version `1.1` adds some improvements on signature validation and solves some namespace conflicts.
|
132
|
+
|
133
|
+
## Upgrading from 0.9.x to 1.0.x
|
134
|
+
|
135
|
+
Version `1.0` is a recommended update for all Ruby SAML users as it includes security fixes.
|
136
|
+
|
137
|
+
Version `1.0` adds security improvements like entity expansion limitation, more SAML message validations, and other important improvements like decrypt support.
|
138
|
+
|
139
|
+
### Important Changes
|
140
|
+
|
141
|
+
Please note the `get_idp_metadata` method raises an exception when it is not able to fetch the idp metadata, so review your integration if you are using this functionality.
|
142
|
+
|
143
|
+
## Upgrading from 0.8.x to 0.9.x
|
144
|
+
|
145
|
+
Version `0.9` adds many new features and improvements.
|
146
|
+
|
147
|
+
## Upgrading from 0.7.x to 0.8.x
|
148
|
+
|
149
|
+
Version `0.8.x` changes the namespace of the gem from `OneLogin::Saml` to `OneLogin::RubySaml`. Please update your implementations of the gem accordingly.
|
@@ -73,7 +73,7 @@ module OneLogin
|
|
73
73
|
base64_request = encode(request)
|
74
74
|
request_params = {"SAMLRequest" => base64_request}
|
75
75
|
|
76
|
-
if settings.
|
76
|
+
if settings.idp_sso_service_binding == Utils::BINDINGS[:redirect] && settings.security[:authn_requests_signed] && settings.private_key
|
77
77
|
params['SigAlg'] = settings.security[:signature_method]
|
78
78
|
url_string = OneLogin::RubySaml::Utils.build_query(
|
79
79
|
:type => 'SAMLRequest',
|
@@ -179,8 +179,7 @@ module OneLogin
|
|
179
179
|
end
|
180
180
|
|
181
181
|
def sign_document(document, settings)
|
182
|
-
|
183
|
-
if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
|
182
|
+
if settings.idp_sso_service_binding == Utils::BINDINGS[:post] && settings.security[:authn_requests_signed] && settings.private_key && settings.certificate
|
184
183
|
private_key = settings.get_sp_key
|
185
184
|
cert = settings.get_sp_cert
|
186
185
|
document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
|
@@ -11,6 +11,10 @@ module OneLogin
|
|
11
11
|
|
12
12
|
# Auxiliary class to retrieve and parse the Identity Provider Metadata
|
13
13
|
#
|
14
|
+
# This class does not validate in any way the URL that is introduced,
|
15
|
+
# make sure to validate it properly before use it in a parse_remote method.
|
16
|
+
# Read the `Security warning` section of the README.md file to get more info
|
17
|
+
#
|
14
18
|
class IdpMetadataParser
|
15
19
|
|
16
20
|
module SamlMetadata
|
@@ -43,7 +47,7 @@ module OneLogin
|
|
43
47
|
SamlMetadata::NAMESPACE
|
44
48
|
)
|
45
49
|
end
|
46
|
-
|
50
|
+
|
47
51
|
# Parse the Identity Provider metadata and update the settings with the
|
48
52
|
# IdP values
|
49
53
|
#
|
@@ -52,9 +56,10 @@ module OneLogin
|
|
52
56
|
#
|
53
57
|
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
|
54
58
|
# @option options [OneLogin::RubySaml::Settings, Hash] :settings the OneLogin::RubySaml::Settings object which gets the parsed metadata merged into or an hash for Settings overrides.
|
55
|
-
# @option options [
|
56
|
-
# @option options [Array<String>, nil] :
|
57
|
-
# @option options [String, nil] :
|
59
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
60
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
61
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
62
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
58
63
|
#
|
59
64
|
# @return [OneLogin::RubySaml::Settings]
|
60
65
|
#
|
@@ -70,9 +75,10 @@ module OneLogin
|
|
70
75
|
# @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
|
71
76
|
#
|
72
77
|
# @param options [Hash] options used for parsing the metadata
|
73
|
-
# @option options [
|
74
|
-
# @option options [Array<String>, nil] :
|
75
|
-
# @option options [String, nil] :
|
78
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
79
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
80
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
81
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
76
82
|
#
|
77
83
|
# @return [Hash]
|
78
84
|
#
|
@@ -87,9 +93,10 @@ module OneLogin
|
|
87
93
|
# @param validate_cert [Boolean] If true and the URL is HTTPs, the cert of the domain is checked.
|
88
94
|
#
|
89
95
|
# @param options [Hash] options used for parsing the metadata
|
90
|
-
# @option options [
|
91
|
-
# @option options [Array<String>, nil] :
|
92
|
-
# @option options [String, nil] :
|
96
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, all found IdPs are returned.
|
97
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
98
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
99
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
93
100
|
#
|
94
101
|
# @return [Array<Hash>]
|
95
102
|
#
|
@@ -105,9 +112,10 @@ module OneLogin
|
|
105
112
|
#
|
106
113
|
# @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object or an hash for Settings overrides
|
107
114
|
# @option options [OneLogin::RubySaml::Settings, Hash] :settings the OneLogin::RubySaml::Settings object which gets the parsed metadata merged into or an hash for Settings overrides.
|
108
|
-
# @option options [
|
109
|
-
# @option options [Array<String>, nil] :
|
110
|
-
# @option options [String, nil] :
|
115
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
116
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
117
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
118
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
111
119
|
#
|
112
120
|
# @return [OneLogin::RubySaml::Settings]
|
113
121
|
def parse(idp_metadata, options = {})
|
@@ -115,8 +123,10 @@ module OneLogin
|
|
115
123
|
|
116
124
|
unless parsed_metadata[:cache_duration].nil?
|
117
125
|
cache_valid_until_timestamp = OneLogin::RubySaml::Utils.parse_duration(parsed_metadata[:cache_duration])
|
118
|
-
|
119
|
-
parsed_metadata[:valid_until]
|
126
|
+
unless cache_valid_until_timestamp.nil?
|
127
|
+
if parsed_metadata[:valid_until].nil? || cache_valid_until_timestamp < Time.parse(parsed_metadata[:valid_until], Time.now.utc).to_i
|
128
|
+
parsed_metadata[:valid_until] = Time.at(cache_valid_until_timestamp).utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
129
|
+
end
|
120
130
|
end
|
121
131
|
end
|
122
132
|
# Remove the cache_duration because on the settings
|
@@ -139,9 +149,10 @@ module OneLogin
|
|
139
149
|
# @param idp_metadata [String]
|
140
150
|
#
|
141
151
|
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
|
142
|
-
# @option options [
|
143
|
-
# @option options [Array<String>, nil] :
|
144
|
-
# @option options [String, nil] :
|
152
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, the first entity descriptor is used.
|
153
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
154
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
155
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
145
156
|
#
|
146
157
|
# @return [Hash]
|
147
158
|
def parse_to_hash(idp_metadata, options = {})
|
@@ -153,13 +164,14 @@ module OneLogin
|
|
153
164
|
# @param idp_metadata [String]
|
154
165
|
#
|
155
166
|
# @param options [Hash] options used for parsing the metadata and the returned Settings instance
|
156
|
-
# @option options [
|
157
|
-
# @option options [Array<String>, nil] :
|
158
|
-
# @option options [String, nil] :
|
167
|
+
# @option options [String, nil] :entity_id when this is given, the entity descriptor for this ID is used. When omitted, all found IdPs are returned.
|
168
|
+
# @option options [String, Array<String>, nil] :sso_binding an ordered list of bindings to detect the single signon URL. The first binding in the list that is included in the metadata will be used.
|
169
|
+
# @option options [String, Array<String>, nil] :slo_binding an ordered list of bindings to detect the single logout URL. The first binding in the list that is included in the metadata will be used.
|
170
|
+
# @option options [String, Array<String>, nil] :name_id_format an ordered list of NameIDFormats to detect a desired value. The first NameIDFormat in the list that is included in the metadata will be used.
|
159
171
|
#
|
160
172
|
# @return [Array<Hash>]
|
161
173
|
def parse_to_array(idp_metadata, options = {})
|
162
|
-
parse_to_idp_metadata_array(idp_metadata, options).map{|idp_md| idp_md.to_hash(options)}
|
174
|
+
parse_to_idp_metadata_array(idp_metadata, options).map { |idp_md| idp_md.to_hash(options) }
|
163
175
|
end
|
164
176
|
|
165
177
|
def parse_to_idp_metadata_array(idp_metadata, options = {})
|
@@ -171,9 +183,9 @@ module OneLogin
|
|
171
183
|
raise ArgumentError.new("idp_metadata must contain an IDPSSODescriptor element")
|
172
184
|
end
|
173
185
|
|
174
|
-
|
186
|
+
idpsso_descriptors.map {|id| IdpMetadata.new(id, id.parent.attributes["entityID"])}
|
175
187
|
end
|
176
|
-
|
188
|
+
|
177
189
|
private
|
178
190
|
|
179
191
|
# Retrieve the remote IdP metadata from the URL or a cached copy.
|
@@ -210,19 +222,23 @@ module OneLogin
|
|
210
222
|
|
211
223
|
class IdpMetadata
|
212
224
|
attr_reader :idpsso_descriptor, :entity_id
|
213
|
-
|
225
|
+
|
214
226
|
def initialize(idpsso_descriptor, entity_id)
|
215
227
|
@idpsso_descriptor = idpsso_descriptor
|
216
228
|
@entity_id = entity_id
|
217
229
|
end
|
218
230
|
|
219
231
|
def to_hash(options = {})
|
232
|
+
sso_binding = options[:sso_binding]
|
233
|
+
slo_binding = options[:slo_binding]
|
220
234
|
{
|
221
235
|
:idp_entity_id => @entity_id,
|
222
|
-
:name_identifier_format => idp_name_id_format,
|
223
|
-
:idp_sso_service_url => single_signon_service_url(
|
224
|
-
:
|
225
|
-
:
|
236
|
+
:name_identifier_format => idp_name_id_format(options[:name_id_format]),
|
237
|
+
:idp_sso_service_url => single_signon_service_url(sso_binding),
|
238
|
+
:idp_sso_service_binding => single_signon_service_binding(sso_binding),
|
239
|
+
:idp_slo_service_url => single_logout_service_url(slo_binding),
|
240
|
+
:idp_slo_service_binding => single_logout_service_binding(slo_binding),
|
241
|
+
:idp_slo_response_service_url => single_logout_response_service_url(slo_binding),
|
226
242
|
:idp_attribute_names => attribute_names,
|
227
243
|
:idp_cert => nil,
|
228
244
|
:idp_cert_fingerprint => nil,
|
@@ -234,17 +250,6 @@ module OneLogin
|
|
234
250
|
end
|
235
251
|
end
|
236
252
|
|
237
|
-
# @return [String|nil] IdP Name ID Format value if exists
|
238
|
-
#
|
239
|
-
def idp_name_id_format
|
240
|
-
node = REXML::XPath.first(
|
241
|
-
@idpsso_descriptor,
|
242
|
-
"md:NameIDFormat",
|
243
|
-
SamlMetadata::NAMESPACE
|
244
|
-
)
|
245
|
-
Utils.element_text(node)
|
246
|
-
end
|
247
|
-
|
248
253
|
# @return [String|nil] 'validUntil' attribute of metadata
|
249
254
|
#
|
250
255
|
def valid_until
|
@@ -259,39 +264,31 @@ module OneLogin
|
|
259
264
|
root.attributes['cacheDuration'] if root && root.attributes
|
260
265
|
end
|
261
266
|
|
262
|
-
# @param
|
263
|
-
# @return [String|nil]
|
267
|
+
# @param name_id_priority [String|Array<String>] The prioritized list of NameIDFormat values to select. Will select first value if nil.
|
268
|
+
# @return [String|nil] IdP NameIDFormat value if exists
|
264
269
|
#
|
265
|
-
def
|
270
|
+
def idp_name_id_format(name_id_priority = nil)
|
266
271
|
nodes = REXML::XPath.match(
|
267
272
|
@idpsso_descriptor,
|
268
|
-
"md:
|
273
|
+
"md:NameIDFormat",
|
269
274
|
SamlMetadata::NAMESPACE
|
270
275
|
)
|
271
|
-
|
272
|
-
values = nodes.map(&:value)
|
273
|
-
binding_priority.detect{ |binding| values.include? binding }
|
274
|
-
else
|
275
|
-
nodes.first.value if nodes.any?
|
276
|
-
end
|
276
|
+
first_ranked_text(nodes, name_id_priority)
|
277
277
|
end
|
278
278
|
|
279
|
-
# @param
|
280
|
-
# @return [String|nil] SingleSignOnService
|
279
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
280
|
+
# @return [String|nil] SingleSignOnService binding if exists
|
281
281
|
#
|
282
|
-
def
|
283
|
-
|
284
|
-
return if binding.nil?
|
285
|
-
|
286
|
-
node = REXML::XPath.first(
|
282
|
+
def single_signon_service_binding(binding_priority = nil)
|
283
|
+
nodes = REXML::XPath.match(
|
287
284
|
@idpsso_descriptor,
|
288
|
-
"md:SingleSignOnService
|
285
|
+
"md:SingleSignOnService/@Binding",
|
289
286
|
SamlMetadata::NAMESPACE
|
290
287
|
)
|
291
|
-
|
288
|
+
first_ranked_value(nodes, binding_priority)
|
292
289
|
end
|
293
290
|
|
294
|
-
# @param binding_priority [Array]
|
291
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
295
292
|
# @return [String|nil] SingleLogoutService binding if exists
|
296
293
|
#
|
297
294
|
def single_logout_service_binding(binding_priority = nil)
|
@@ -300,19 +297,29 @@ module OneLogin
|
|
300
297
|
"md:SingleLogoutService/@Binding",
|
301
298
|
SamlMetadata::NAMESPACE
|
302
299
|
)
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
300
|
+
first_ranked_value(nodes, binding_priority)
|
301
|
+
end
|
302
|
+
|
303
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
304
|
+
# @return [String|nil] SingleSignOnService endpoint if exists
|
305
|
+
#
|
306
|
+
def single_signon_service_url(binding_priority = nil)
|
307
|
+
binding = single_signon_service_binding(binding_priority)
|
308
|
+
return if binding.nil?
|
309
|
+
|
310
|
+
node = REXML::XPath.first(
|
311
|
+
@idpsso_descriptor,
|
312
|
+
"md:SingleSignOnService[@Binding=\"#{binding}\"]/@Location",
|
313
|
+
SamlMetadata::NAMESPACE
|
314
|
+
)
|
315
|
+
node.value if node
|
309
316
|
end
|
310
317
|
|
311
|
-
# @param
|
318
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
312
319
|
# @return [String|nil] SingleLogoutService endpoint if exists
|
313
320
|
#
|
314
|
-
def single_logout_service_url(
|
315
|
-
binding = single_logout_service_binding(
|
321
|
+
def single_logout_service_url(binding_priority = nil)
|
322
|
+
binding = single_logout_service_binding(binding_priority)
|
316
323
|
return if binding.nil?
|
317
324
|
|
318
325
|
node = REXML::XPath.first(
|
@@ -320,14 +327,14 @@ module OneLogin
|
|
320
327
|
"md:SingleLogoutService[@Binding=\"#{binding}\"]/@Location",
|
321
328
|
SamlMetadata::NAMESPACE
|
322
329
|
)
|
323
|
-
|
330
|
+
node.value if node
|
324
331
|
end
|
325
332
|
|
326
|
-
# @param
|
333
|
+
# @param binding_priority [String|Array<String>] The prioritized list of Binding values to select. Will select first value if nil.
|
327
334
|
# @return [String|nil] SingleLogoutService response url if exists
|
328
335
|
#
|
329
|
-
def single_logout_response_service_url(
|
330
|
-
binding = single_logout_service_binding(
|
336
|
+
def single_logout_response_service_url(binding_priority = nil)
|
337
|
+
binding = single_logout_service_binding(binding_priority)
|
331
338
|
return if binding.nil?
|
332
339
|
|
333
340
|
node = REXML::XPath.first(
|
@@ -335,7 +342,7 @@ module OneLogin
|
|
335
342
|
"md:SingleLogoutService[@Binding=\"#{binding}\"]/@ResponseLocation",
|
336
343
|
SamlMetadata::NAMESPACE
|
337
344
|
)
|
338
|
-
|
345
|
+
node.value if node
|
339
346
|
end
|
340
347
|
|
341
348
|
# @return [String|nil] Unformatted Certificate if exists
|
@@ -417,15 +424,41 @@ module OneLogin
|
|
417
424
|
parsed_metadata[:idp_cert_fingerprint_algorithm]
|
418
425
|
)
|
419
426
|
end
|
420
|
-
else
|
421
|
-
# symbolize keys of certificates and pass it on
|
422
|
-
parsed_metadata[:idp_cert_multi] = Hash[certificates.map { |k, v| [k.to_sym, v] }]
|
423
427
|
end
|
428
|
+
|
429
|
+
# symbolize keys of certificates and pass it on
|
430
|
+
parsed_metadata[:idp_cert_multi] = Hash[certificates.map { |k, v| [k.to_sym, v] }]
|
424
431
|
end
|
425
432
|
|
426
433
|
def certificates_has_one(key)
|
427
434
|
certificates.key?(key) && certificates[key].size == 1
|
428
435
|
end
|
436
|
+
|
437
|
+
private
|
438
|
+
|
439
|
+
def first_ranked_text(nodes, priority = nil)
|
440
|
+
return unless nodes.any?
|
441
|
+
|
442
|
+
priority = Array(priority)
|
443
|
+
if priority.any?
|
444
|
+
values = nodes.map(&:text)
|
445
|
+
Array(priority).detect { |candidate| values.include?(candidate) }
|
446
|
+
else
|
447
|
+
nodes.first.text
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
def first_ranked_value(nodes, priority = nil)
|
452
|
+
return unless nodes.any?
|
453
|
+
|
454
|
+
priority = Array(priority)
|
455
|
+
if priority.any?
|
456
|
+
values = nodes.map(&:value)
|
457
|
+
priority.detect { |candidate| values.include?(candidate) }
|
458
|
+
else
|
459
|
+
nodes.first.value
|
460
|
+
end
|
461
|
+
end
|
429
462
|
end
|
430
463
|
|
431
464
|
def merge_parsed_metadata_into(settings, parsed_metadata)
|
@@ -70,8 +70,8 @@ module OneLogin
|
|
70
70
|
base64_request = encode(request)
|
71
71
|
request_params = {"SAMLRequest" => base64_request}
|
72
72
|
|
73
|
-
if settings.
|
74
|
-
params['SigAlg']
|
73
|
+
if settings.idp_slo_service_binding == Utils::BINDINGS[:redirect] && settings.security[:logout_requests_signed] && settings.private_key
|
74
|
+
params['SigAlg'] = settings.security[:signature_method]
|
75
75
|
url_string = OneLogin::RubySaml::Utils.build_query(
|
76
76
|
:type => 'SAMLRequest',
|
77
77
|
:data => base64_request,
|
@@ -138,7 +138,7 @@ module OneLogin
|
|
138
138
|
|
139
139
|
def sign_document(document, settings)
|
140
140
|
# embed signature
|
141
|
-
if settings.
|
141
|
+
if settings.idp_slo_service_binding == Utils::BINDINGS[:post] && settings.security[:logout_requests_signed] && settings.private_key && settings.certificate
|
142
142
|
private_key = settings.get_sp_key
|
143
143
|
cert = settings.get_sp_cert
|
144
144
|
document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
|
@@ -43,7 +43,7 @@ module OneLogin
|
|
43
43
|
end
|
44
44
|
|
45
45
|
@options = options
|
46
|
-
@response = decode_raw_saml(response)
|
46
|
+
@response = decode_raw_saml(response, settings)
|
47
47
|
@document = XMLSecurity::SignedDocument.new(@response)
|
48
48
|
end
|
49
49
|
|
@@ -150,8 +150,7 @@ module OneLogin
|
|
150
150
|
# @raise [ValidationError] if soft == false and validation fails
|
151
151
|
#
|
152
152
|
def validate_structure
|
153
|
-
|
154
|
-
unless valid_saml?(document, soft, check_malformed_doc)
|
153
|
+
unless valid_saml?(document, soft)
|
155
154
|
return append_error("Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd")
|
156
155
|
end
|
157
156
|
|