libsaml 3.6.0 → 3.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -3
- data/lib/saml.rb +2 -0
- data/lib/saml/assertion.rb +2 -1
- data/lib/saml/bindings/http_post.rb +6 -1
- data/lib/saml/bindings/http_redirect.rb +8 -3
- data/lib/saml/elements/authn_statement.rb +1 -0
- data/lib/saml/elements/encrypted_attribute.rb +1 -19
- data/lib/saml/elements/encrypted_id.rb +11 -32
- data/lib/saml/response.rb +6 -2
- data/lib/saml/util.rb +32 -1
- data/lib/saml/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 80a144ab0df42eeb447e74d6df3f3a19a7d89e72cf5527277403b229eb87216c
|
4
|
+
data.tar.gz: cd41e41d4f0492e98c52ea9c6865e958a0896c0522f987b58175c69e2d23eaac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 258f442a035b8e06cb9896ed2faf0c5e88d4d58c63ddfcbcd19b14b937fed2de1482aa89bd92bf3b8bcff20f32e5c65b0f92355eefcb1abe0944f2c14a470b45
|
7
|
+
data.tar.gz: faa732f728819578d2e75a73129148da7e74eefca3d5ef7a033b7926d2266c417f9c52666dae8c0eef5f3c6fa06032b6da2bdf7eb5118ba4fb9758d127d8f626
|
data/README.md
CHANGED
@@ -94,10 +94,10 @@ Now you can make a SAML controller in `app/controllers/saml_controller.rb`:
|
|
94
94
|
```ruby
|
95
95
|
class SamlController < ApplicationController
|
96
96
|
extend Saml::Rails::ControllerHelper
|
97
|
-
current_provider "
|
97
|
+
current_provider "<sp_entity_id>"
|
98
98
|
|
99
99
|
def request_authentication
|
100
|
-
provider = Saml.provider("
|
100
|
+
provider = Saml.provider("<idp_enity_id>")
|
101
101
|
destination = provider.single_sign_on_service_url(Saml::ProtocolBinding::HTTP_POST)
|
102
102
|
|
103
103
|
authn_request = Saml::AuthnRequest.new(destination: destination)
|
@@ -153,7 +153,7 @@ Below is an example of a very primitive IDP Saml Controller
|
|
153
153
|
```ruby
|
154
154
|
class SamlController < ActionController::Base
|
155
155
|
extend Saml::Rails::ControllerHelper
|
156
|
-
current_provider "
|
156
|
+
current_provider "<idp_entity_id>"
|
157
157
|
|
158
158
|
def receive_authn_request
|
159
159
|
authn_request = if request.get?
|
@@ -227,6 +227,10 @@ class SamlController < ActionController::Base
|
|
227
227
|
end
|
228
228
|
```
|
229
229
|
|
230
|
+
## Caveats
|
231
|
+
|
232
|
+
- SAMLResponse and Assertions have to be signed as per the SAML security guidelines (Some IDP's don't do this by default and require special configuration)
|
233
|
+
|
230
234
|
## Contributing
|
231
235
|
|
232
236
|
- Fork the project
|
data/lib/saml.rb
CHANGED
data/lib/saml/assertion.rb
CHANGED
@@ -46,7 +46,8 @@ module Saml
|
|
46
46
|
@authn_statement = Saml::Elements::AuthnStatement.new(authn_instant: authn_instant,
|
47
47
|
address: options.delete(:address),
|
48
48
|
authn_context_class_ref: options.delete(:authn_context_class_ref),
|
49
|
-
session_index: options.delete(:session_index)
|
49
|
+
session_index: options.delete(:session_index),
|
50
|
+
session_not_on_or_after: options.delete(:session_not_on_or_after))
|
50
51
|
super(*(args << options))
|
51
52
|
@_id ||= Saml.generate_id
|
52
53
|
@issue_instant ||= Time.now
|
@@ -20,7 +20,12 @@ module Saml
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def receive_message(request, type)
|
23
|
-
|
23
|
+
receive_xml = request.params["SAMLRequest"] || request.params["SAMLResponse"]
|
24
|
+
if receive_xml.nil?
|
25
|
+
raise Saml::Errors::InvalidParams, 'require params `SAMLRequest` or `SAMLResponse`'
|
26
|
+
end
|
27
|
+
|
28
|
+
message = Saml::Encoding.decode_64(receive_xml)
|
24
29
|
notify('receive_message', message)
|
25
30
|
request_or_response = Saml.parse_message(message, type)
|
26
31
|
|
@@ -5,7 +5,7 @@ module Saml
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
def create_url(request_or_response, options = {})
|
8
|
-
options[:signature_algorithm] ||= 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
|
8
|
+
options[:signature_algorithm] ||= 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' unless options[:exclude_signature]
|
9
9
|
new(request_or_response, options).create_url
|
10
10
|
end
|
11
11
|
|
@@ -42,13 +42,14 @@ module Saml
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
attr_accessor :request_or_response, :signature_algorithm, :relay_state, :signature
|
45
|
+
attr_accessor :request_or_response, :signature_algorithm, :relay_state, :signature, :exclude_signature
|
46
46
|
|
47
47
|
def initialize(request_or_response, options = {})
|
48
48
|
@request_or_response = request_or_response
|
49
49
|
@signature_algorithm = options[:signature_algorithm]
|
50
50
|
@relay_state = options[:relay_state]
|
51
51
|
@signature = options[:signature]
|
52
|
+
@exclude_signature = options[:exclude_signature]
|
52
53
|
end
|
53
54
|
|
54
55
|
def verify_signature(query)
|
@@ -61,7 +62,7 @@ module Saml
|
|
61
62
|
url = request_or_response.destination
|
62
63
|
delimiter = url.include?('?') ? '&' : '?'
|
63
64
|
|
64
|
-
[url, signed_params].join(delimiter)
|
65
|
+
[url, exclude_signature ? unsigned_params : signed_params].join(delimiter)
|
65
66
|
end
|
66
67
|
|
67
68
|
private
|
@@ -108,6 +109,10 @@ module Saml
|
|
108
109
|
|
109
110
|
"#{encoded_params}&Signature=#{encoded_signature}"
|
110
111
|
end
|
112
|
+
|
113
|
+
def unsigned_params
|
114
|
+
encoded_params.to_s
|
115
|
+
end
|
111
116
|
end
|
112
117
|
end
|
113
118
|
end
|
@@ -8,6 +8,7 @@ module Saml
|
|
8
8
|
|
9
9
|
attribute :authn_instant, Time, tag: "AuthnInstant", on_save: lambda { |val| val.utc.xmlschema }
|
10
10
|
attribute :session_index, String, tag: "SessionIndex"
|
11
|
+
attribute :session_not_on_or_after, Time, tag: "SessionNotOnOrAfter", on_save: lambda { |val| val.utc.xmlschema if val.present?}
|
11
12
|
|
12
13
|
has_one :subject_locality, Saml::Elements::SubjectLocality, tag: "SubjectLocality"
|
13
14
|
has_one :authn_context, Saml::Elements::AuthnContext, tag: "AuthnContext"
|
@@ -15,27 +15,9 @@ module Saml
|
|
15
15
|
validates :encrypted_data, presence: true
|
16
16
|
|
17
17
|
def encrypt(attribute, encrypted_key_data, encrypted_data_options = {})
|
18
|
-
self
|
19
|
-
self.encrypted_data.set_encryption_method algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
|
20
|
-
self.encrypted_data.set_key_name key_name
|
21
|
-
|
22
|
-
encrypted_key_data.each do |key_descriptor, key_options|
|
23
|
-
encrypted_key = self.encrypted_data.encrypt Nokogiri::XML(attribute.to_xml).root.to_xml, key_options
|
24
|
-
encrypted_key.set_encryption_method algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p', digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1'
|
25
|
-
encrypted_key.set_key_name key_descriptor.key_info.key_name
|
26
|
-
encrypted_key.carried_key_name = key_name
|
27
|
-
encrypted_key.encrypt key_descriptor.certificate.public_key
|
28
|
-
|
29
|
-
self.encrypted_keys ||= []
|
30
|
-
self.encrypted_keys << encrypted_key
|
31
|
-
end
|
18
|
+
Saml::Util.encrypt_element(self, attribute, encrypted_key_data, encrypted_data_options)
|
32
19
|
end
|
33
20
|
|
34
|
-
private
|
35
|
-
|
36
|
-
def key_name
|
37
|
-
@key_name ||= Saml.generate_id
|
38
|
-
end
|
39
21
|
end
|
40
22
|
end
|
41
23
|
end
|
@@ -28,16 +28,16 @@ module Saml
|
|
28
28
|
|
29
29
|
if key_descriptors.any?
|
30
30
|
if key_descriptors.one?
|
31
|
-
|
31
|
+
encrypt_for_one_key_descriptor(key_descriptors.first, key_options)
|
32
32
|
else
|
33
|
-
|
33
|
+
encrypt_for_multiple_key_descriptors(key_descriptors, key_options)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
private
|
39
39
|
|
40
|
-
def
|
40
|
+
def encrypt_for_one_key_descriptor(key_descriptor, key_options = {})
|
41
41
|
self.encrypted_data = Xmlenc::Builder::EncryptedData.new
|
42
42
|
|
43
43
|
self.encrypted_data.set_key_retrieval_method Xmlenc::Builder::RetrievalMethod.new(
|
@@ -47,7 +47,7 @@ module Saml
|
|
47
47
|
algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
|
48
48
|
)
|
49
49
|
|
50
|
-
encrypted_key = self.encrypted_data.encrypt(
|
50
|
+
encrypted_key = self.encrypted_data.encrypt(Nokogiri::XML(name_id.to_xml).root.to_xml, key_options)
|
51
51
|
encrypted_key.set_encryption_method(
|
52
52
|
algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p',
|
53
53
|
digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1'
|
@@ -60,39 +60,18 @@ module Saml
|
|
60
60
|
self.name_id = nil
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
self.encrypted_data.set_key_name key_name
|
69
|
-
self.encrypted_data.set_encryption_method(
|
70
|
-
algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
|
71
|
-
)
|
72
|
-
|
73
|
-
key_descriptors.each do |key_descriptor|
|
74
|
-
encrypted_key = self.encrypted_data.encrypt(
|
75
|
-
name_id_xml,
|
76
|
-
key_options.merge(id: "_#{SecureRandom.uuid}", carried_key_name: key_name)
|
77
|
-
)
|
78
|
-
encrypted_key.set_encryption_method(
|
79
|
-
algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p',
|
80
|
-
digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1'
|
81
|
-
)
|
82
|
-
|
83
|
-
encrypted_key.set_key_name(key_descriptor.key_info.key_name)
|
84
|
-
encrypted_key.encrypt(key_descriptor.certificate.public_key)
|
85
|
-
|
86
|
-
encrypted_keys << encrypted_key
|
63
|
+
def encrypt_for_multiple_key_descriptors(encrypted_key_data, encrypted_data_options = {})
|
64
|
+
if encrypted_data_options[:recipient].present? && encrypted_key_data.first.is_a?(Saml::Elements::KeyDescriptor)
|
65
|
+
encrypted_key_data.map! do |key_descriptor|
|
66
|
+
[ key_descriptor, { recipient: encrypted_data_options[:recipient] } ]
|
67
|
+
end
|
87
68
|
end
|
88
69
|
|
89
|
-
self
|
70
|
+
Saml::Util.encrypt_element(self, name_id, encrypted_key_data, encrypted_data_options)
|
71
|
+
|
90
72
|
self.name_id = nil
|
91
73
|
end
|
92
74
|
|
93
|
-
def name_id_xml
|
94
|
-
Nokogiri::XML(name_id.to_xml).root.to_xml
|
95
|
-
end
|
96
75
|
end
|
97
76
|
end
|
98
77
|
end
|
data/lib/saml/response.rb
CHANGED
@@ -28,10 +28,14 @@ module Saml
|
|
28
28
|
!success? && status.status_code.unknown_principal?
|
29
29
|
end
|
30
30
|
|
31
|
-
def encrypt_assertions(
|
31
|
+
def encrypt_assertions(key_descriptor_or_certificate, include_certificate: false, include_key_retrieval_method: false)
|
32
32
|
@encrypted_assertions = []
|
33
33
|
assertions.each do |assertion|
|
34
|
-
@encrypted_assertions << Saml::Util.encrypt_assertion(
|
34
|
+
@encrypted_assertions << Saml::Util.encrypt_assertion(
|
35
|
+
assertion, key_descriptor_or_certificate,
|
36
|
+
include_certificate: include_certificate,
|
37
|
+
include_key_retrieval_method: include_key_retrieval_method
|
38
|
+
)
|
35
39
|
end
|
36
40
|
assertions.clear
|
37
41
|
end
|
data/lib/saml/util.rb
CHANGED
@@ -60,7 +60,7 @@ module Saml
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
def encrypt_assertion(assertion, key_descriptor_or_certificate, include_certificate: false)
|
63
|
+
def encrypt_assertion(assertion, key_descriptor_or_certificate, include_certificate: false, include_key_retrieval_method: false)
|
64
64
|
case key_descriptor_or_certificate
|
65
65
|
when OpenSSL::X509::Certificate
|
66
66
|
certificate = key_descriptor_or_certificate
|
@@ -87,6 +87,11 @@ module Saml
|
|
87
87
|
end
|
88
88
|
encrypted_key.encrypt(certificate.public_key)
|
89
89
|
|
90
|
+
if include_key_retrieval_method
|
91
|
+
encrypted_key.id = '_' + SecureRandom.uuid
|
92
|
+
encrypted_data.set_key_retrieval_method (Xmlenc::Builder::RetrievalMethod.new(uri: "##{encrypted_key.id}"))
|
93
|
+
end
|
94
|
+
|
90
95
|
Saml::Elements::EncryptedAssertion.new(encrypted_data: encrypted_data, encrypted_keys: encrypted_key)
|
91
96
|
end
|
92
97
|
|
@@ -98,6 +103,32 @@ module Saml
|
|
98
103
|
Saml::Assertion.parse(encrypted_document.decrypt(private_key), single: true)
|
99
104
|
end
|
100
105
|
|
106
|
+
def encrypt_element(element, target_element, encrypted_key_data, encrypted_data_options)
|
107
|
+
key_name = encrypted_data_options.fetch(:key_name, Saml.generate_id)
|
108
|
+
|
109
|
+
element.encrypted_data = Xmlenc::Builder::EncryptedData.new(encrypted_data_options)
|
110
|
+
element.encrypted_data.set_encryption_method(algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc')
|
111
|
+
element.encrypted_data.set_key_name key_name
|
112
|
+
|
113
|
+
original_encrypted_key = element.encrypted_data.encrypt(Nokogiri::XML(target_element.to_xml).root.to_xml, encrypted_data_options)
|
114
|
+
|
115
|
+
encrypted_key_data.each do |key_descriptor, key_options = {}|
|
116
|
+
encrypted_key_options = key_options.merge(id: Saml.generate_id, data: original_encrypted_key.data)
|
117
|
+
|
118
|
+
encrypted_key = Xmlenc::Builder::EncryptedKey.new(encrypted_key_options)
|
119
|
+
encrypted_key.add_data_reference(element.encrypted_data.id)
|
120
|
+
encrypted_key.set_key_name(key_descriptor.key_info.key_name)
|
121
|
+
encrypted_key.carried_key_name = key_name
|
122
|
+
encrypted_key.set_encryption_method(algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p', digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1')
|
123
|
+
encrypted_key.encrypt(key_descriptor.certificate.public_key)
|
124
|
+
|
125
|
+
element.encrypted_keys ||= []
|
126
|
+
element.encrypted_keys << encrypted_key
|
127
|
+
end
|
128
|
+
|
129
|
+
element
|
130
|
+
end
|
131
|
+
|
101
132
|
def encrypt_name_id(name_id, key_descriptor, key_options = {})
|
102
133
|
encrypted_id = Saml::Elements::EncryptedID.new(name_id: name_id)
|
103
134
|
encrypt_encrypted_id(encrypted_id, key_descriptor, key_options)
|
data/lib/saml/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libsaml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benoist Claassen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -240,7 +240,7 @@ homepage: https://www.digidentity.eu
|
|
240
240
|
licenses:
|
241
241
|
- MIT
|
242
242
|
metadata: {}
|
243
|
-
post_install_message:
|
243
|
+
post_install_message:
|
244
244
|
rdoc_options: []
|
245
245
|
require_paths:
|
246
246
|
- lib
|
@@ -256,7 +256,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
256
256
|
version: '0'
|
257
257
|
requirements: []
|
258
258
|
rubygems_version: 3.0.3
|
259
|
-
signing_key:
|
259
|
+
signing_key:
|
260
260
|
specification_version: 4
|
261
261
|
summary: A gem to easily create SAML 2.0 messages.
|
262
262
|
test_files: []
|