saml2 3.1.10 → 3.2.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 +4 -4
- data/app/views/saml2/http_post.html.erb +9 -2
- data/exe/bulk_verify_responses +1 -1
- data/lib/saml2/authn_request.rb +12 -5
- data/lib/saml2/base.rb +10 -4
- data/lib/saml2/conditions.rb +2 -2
- data/lib/saml2/endpoint.rb +115 -19
- data/lib/saml2/entity.rb +3 -3
- data/lib/saml2/identity_provider.rb +2 -2
- data/lib/saml2/indexed_object.rb +13 -5
- data/lib/saml2/logout_request.rb +4 -3
- data/lib/saml2/logout_response.rb +12 -3
- data/lib/saml2/message.rb +2 -1
- data/lib/saml2/name_id.rb +17 -2
- data/lib/saml2/response.rb +9 -4
- data/lib/saml2/role.rb +0 -2
- data/lib/saml2/service_provider.rb +6 -8
- data/lib/saml2/signable.rb +2 -2
- data/lib/saml2/sso.rb +2 -2
- data/lib/saml2/status.rb +3 -1
- data/lib/saml2/version.rb +1 -1
- metadata +4 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f582a823ae927adc8355f2c3b294c8d592a108a60995d8e156548fabb2530e7c
|
4
|
+
data.tar.gz: 2a596f2b0705d3b9a365a63721b80a0c977a88315cd70c965ac7166913a12948
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1140328e3e03194e0d6f7b1046abb89525eb0f7151a838fd313c3bd93ae91fe71f6bcc022474c1aba6b674b48e3a09627003248d8040d4a891c05f86ebe99bc
|
7
|
+
data.tar.gz: 3d5c8a0f2e35fdb4017f35bea6a547f05cf53d4c8ce4b43672d18a2a7485f373a0accd4cc87322635be6dcae392cec0095bff7ae4e3db0856f70588cb261331a
|
@@ -5,8 +5,15 @@
|
|
5
5
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
6
6
|
</head>
|
7
7
|
<body onload="document.forms[0].submit();" style="visibility:hidden;">
|
8
|
-
|
9
|
-
|
8
|
+
<%
|
9
|
+
target = @saml_destination || @saml_acs_url
|
10
|
+
message = @saml_request || @saml_response || @saml_message
|
11
|
+
target ||= message.destination if message.is_a?(SAML2::Message)
|
12
|
+
message = Base64.encode64(message.to_s) unless message.is_a?(String)
|
13
|
+
%>
|
14
|
+
<%= form_tag(target) do %>
|
15
|
+
<%= hidden_field_tag("SAMLRequest", message) if @saml_request || @saml_message.is_a?(SAML2::Request) %>
|
16
|
+
<%= hidden_field_tag("SAMLResponse", message) if @saml_response || @saml_message.is_a?(SAML2::Response) %>
|
10
17
|
<%= hidden_field_tag("RelayState", @relay_state) if @relay_state %>
|
11
18
|
<%= submit_tag "Submit" %>
|
12
19
|
<% end %>
|
data/exe/bulk_verify_responses
CHANGED
@@ -82,7 +82,7 @@ responses.each_with_index do |response_raw, i|
|
|
82
82
|
# TODO: ignore audience restrictions
|
83
83
|
errors = response.validate(service_provider: service_provider_entity,
|
84
84
|
identity_provider: idps[response.issuer&.id],
|
85
|
-
verification_time:
|
85
|
+
verification_time:)
|
86
86
|
unless errors.empty?
|
87
87
|
bad_counts[response.issuer&.id] += 1
|
88
88
|
warn "#{errors.inspect} for response #{response.id} from #{response.issuer&.id} (index #{i})"
|
data/lib/saml2/authn_request.rb
CHANGED
@@ -30,16 +30,23 @@ module SAML2
|
|
30
30
|
# @todo go over these params, and use kwargs. Maybe pass Entity instead
|
31
31
|
# of ServiceProvider.
|
32
32
|
# @param issuer [NameID]
|
33
|
-
# @param identity_provider [IdentityProvider]
|
34
|
-
# @param assertion_consumer_service [Endpoint::Indexed]
|
35
|
-
# @param service_provider [ServiceProvider]
|
33
|
+
# @param identity_provider [IdentityProvider, nil]
|
34
|
+
# @param assertion_consumer_service [Endpoint::Indexed, nil]
|
35
|
+
# @param service_provider [ServiceProvider, nil]
|
36
|
+
# @param binding [String] the binding to use for the request
|
36
37
|
# @return [AuthnRequest]
|
37
38
|
def self.initiate(issuer, identity_provider = nil,
|
38
39
|
assertion_consumer_service: nil,
|
39
|
-
service_provider: nil
|
40
|
+
service_provider: nil,
|
41
|
+
binding: Bindings::HTTPRedirect::URN)
|
40
42
|
authn_request = new
|
41
43
|
authn_request.issuer = issuer
|
42
|
-
|
44
|
+
if identity_provider
|
45
|
+
authn_request.destination = identity_provider
|
46
|
+
.single_sign_on_services
|
47
|
+
.choose_endpoint(binding)
|
48
|
+
&.location
|
49
|
+
end
|
43
50
|
authn_request.name_id_policy = NameID::Policy.new(true, NameID::Format::UNSPECIFIED)
|
44
51
|
assertion_consumer_service ||= service_provider.assertion_consumer_services.default if service_provider
|
45
52
|
if assertion_consumer_service
|
data/lib/saml2/base.rb
CHANGED
@@ -30,7 +30,10 @@ module SAML2
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def load_object_array(node, element, klass = nil)
|
33
|
-
node.xpath(element, Namespaces::ALL)
|
33
|
+
nodes = node.xpath(element, Namespaces::ALL)
|
34
|
+
return klass::Array.from_xml(nodes) if klass.is_a?(Module) && klass&.const_defined?(:Array, false)
|
35
|
+
|
36
|
+
nodes.map do |element_node|
|
34
37
|
if klass.nil?
|
35
38
|
SAML2.const_get(element_node.name, false).from_xml(element_node)
|
36
39
|
elsif klass.is_a?(Hash)
|
@@ -107,10 +110,10 @@ module SAML2
|
|
107
110
|
# @return [String]
|
108
111
|
def inspect
|
109
112
|
"#<#{self.class.name} #{instance_variables.filter_map do |iv|
|
110
|
-
next if iv
|
113
|
+
next if IGNORED_IVARS.include?(iv)
|
111
114
|
|
112
115
|
"#{iv}=#{instance_variable_get(iv).inspect}"
|
113
|
-
end.join("
|
116
|
+
end.join(" ")}>"
|
114
117
|
end
|
115
118
|
|
116
119
|
# Serialize this object to XML
|
@@ -174,7 +177,7 @@ module SAML2
|
|
174
177
|
|
175
178
|
old_node = node.parent
|
176
179
|
this_nodes_keys.each_with_index do |key, i|
|
177
|
-
old_node.replace(node.decrypt_with(key:
|
180
|
+
old_node.replace(node.decrypt_with(key:))
|
178
181
|
rescue XMLSec::DecryptionError
|
179
182
|
# swallow errors on all but the last key
|
180
183
|
raise if i - 1 == this_nodes_keys.length
|
@@ -185,6 +188,9 @@ module SAML2
|
|
185
188
|
|
186
189
|
private
|
187
190
|
|
191
|
+
IGNORED_IVARS = %i[@errors @pretty @xml].freeze
|
192
|
+
private_constant :IGNORED_IVARS
|
193
|
+
|
188
194
|
def load_string_array(node, element)
|
189
195
|
self.class.load_string_array(node, element)
|
190
196
|
end
|
data/lib/saml2/conditions.rb
CHANGED
@@ -62,8 +62,8 @@ module SAML2
|
|
62
62
|
|
63
63
|
# Use validate instead.
|
64
64
|
# @deprecated
|
65
|
-
def valid?(now: Time.now.utc, **
|
66
|
-
validate(verification_time: now, **
|
65
|
+
def valid?(now: Time.now.utc, **)
|
66
|
+
validate(verification_time: now, **).empty?
|
67
67
|
end
|
68
68
|
|
69
69
|
# (see Base#build)
|
data/lib/saml2/endpoint.rb
CHANGED
@@ -4,21 +4,112 @@ require "saml2/bindings/http_post"
|
|
4
4
|
|
5
5
|
module SAML2
|
6
6
|
class Endpoint < Base
|
7
|
+
module ChoiceHelpers
|
8
|
+
# Choose a binding supported by this list of endpoints
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
def choose_binding(*bindings)
|
12
|
+
(bindings & map(&:binding)).first
|
13
|
+
end
|
14
|
+
|
15
|
+
# Choose an endpoint from this list of endpoints that supports a given binding
|
16
|
+
#
|
17
|
+
# @param binding [String] the binding that must match
|
18
|
+
# @return [Endpoint, nil]
|
19
|
+
def choose_endpoint(binding)
|
20
|
+
find { |endpoint| endpoint.binding == binding }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Array < ::Array
|
25
|
+
include ChoiceHelpers
|
26
|
+
|
27
|
+
def self.from_xml(nodes)
|
28
|
+
new(nodes.map do |node|
|
29
|
+
Endpoint.from_xml(node)
|
30
|
+
end).freeze
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Indexed < Endpoint
|
35
|
+
include IndexedObject
|
36
|
+
|
37
|
+
class Array
|
38
|
+
include ChoiceHelpers
|
39
|
+
|
40
|
+
# Choose a binding supported by this list of endpoints
|
41
|
+
#
|
42
|
+
# Note that if there is a default endpoint, its binding will be preferred even
|
43
|
+
# over the order of the bindings passed in (as long as it is included in the list
|
44
|
+
# at all).
|
45
|
+
# @return [String]
|
46
|
+
def choose_binding(*bindings)
|
47
|
+
return default.binding if default && bindings.include?(default.binding)
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
# Choose an endpoint from this list of endpoints that supports a given binding
|
53
|
+
#
|
54
|
+
# Note that if there is a default endpoint, it will be returned if its binding matches
|
55
|
+
# even over earlier endpoints in the list.
|
56
|
+
# @param binding [String] the binding that must match
|
57
|
+
# @return [Endpoint, nil]
|
58
|
+
def choose_endpoint(binding)
|
59
|
+
return default if default && default.binding == binding
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param location [String]
|
66
|
+
# @param index [Integer]
|
67
|
+
# @param is_default [true, false, nil]
|
68
|
+
# @param binding [String]
|
69
|
+
# @param response_location [String, nil]
|
70
|
+
def initialize(location = nil,
|
71
|
+
index = nil,
|
72
|
+
is_default = nil,
|
73
|
+
binding = Bindings::HTTP_POST::URN,
|
74
|
+
response_location = nil)
|
75
|
+
super(location, binding, response_location)
|
76
|
+
@index = index
|
77
|
+
@is_default = is_default
|
78
|
+
end
|
79
|
+
|
80
|
+
def eql?(other)
|
81
|
+
location == other.location &&
|
82
|
+
binding == other.binding &&
|
83
|
+
response_location == other.response_location &&
|
84
|
+
super
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [String]
|
88
|
+
def inspect
|
89
|
+
"#<SAML2::Endpoint::Indexed #{endpoint_inspect} #{indexed_object_inspect}>"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
7
93
|
# @return [String]
|
8
|
-
|
94
|
+
attr_accessor :location, :binding
|
95
|
+
# @return [String, nil]
|
96
|
+
attr_accessor :response_location
|
9
97
|
|
10
98
|
# @param location [String]
|
11
99
|
# @param binding [String]
|
12
|
-
|
100
|
+
# @param response_location [String, nil]
|
101
|
+
def initialize(location = nil, binding = Bindings::HTTP_POST::URN, response_location = nil)
|
13
102
|
super()
|
14
103
|
@location = location
|
15
104
|
@binding = binding
|
105
|
+
@response_location = response_location
|
16
106
|
end
|
17
107
|
|
18
108
|
# @param rhs [Endpoint]
|
19
109
|
# @return [Boolean]
|
20
110
|
def ==(other)
|
21
|
-
|
111
|
+
other.is_a?(Endpoint) &&
|
112
|
+
location == other.location && binding == other.binding && response_location == other.response_location
|
22
113
|
end
|
23
114
|
|
24
115
|
# (see Base#from_xml)
|
@@ -26,30 +117,35 @@ module SAML2
|
|
26
117
|
super
|
27
118
|
@location = node["Location"]
|
28
119
|
@binding = node["Binding"]
|
120
|
+
@response_location = node["ResponseLocation"]
|
29
121
|
end
|
30
122
|
|
31
123
|
# (see Base#build)
|
32
124
|
def build(builder, element)
|
33
|
-
builder["md"].__send__(element, "Location" => location, "Binding" => binding)
|
125
|
+
builder["md"].__send__(element, "Location" => location, "Binding" => binding) do |b|
|
126
|
+
b.ResponseLocation = response_location if response_location
|
127
|
+
end
|
34
128
|
end
|
35
129
|
|
36
|
-
|
37
|
-
|
130
|
+
# @!attribute[r]
|
131
|
+
# @return [String]
|
132
|
+
# The {response_location} if there is one, otherwise the {location}
|
133
|
+
def effective_response_location
|
134
|
+
response_location || location
|
135
|
+
end
|
38
136
|
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
|
43
|
-
def initialize(location = nil, index = nil, is_default = nil, binding = Bindings::HTTP_POST::URN)
|
44
|
-
super(location, binding)
|
45
|
-
@index = index
|
46
|
-
@is_default = is_default
|
47
|
-
end
|
137
|
+
# @return [String]
|
138
|
+
def inspect
|
139
|
+
"#<SAML2::Endpoint #{endpoint_inspect}>"
|
140
|
+
end
|
48
141
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
142
|
+
private
|
143
|
+
|
144
|
+
def endpoint_inspect
|
145
|
+
r = "location=#{location.inspect}"
|
146
|
+
r += " binding=#{binding.inspect}" if binding
|
147
|
+
r += " response_location=#{response_location.inspect}" if response_location
|
148
|
+
r
|
53
149
|
end
|
54
150
|
end
|
55
151
|
end
|
data/lib/saml2/entity.rb
CHANGED
@@ -168,15 +168,15 @@ module SAML2
|
|
168
168
|
# @param identity_provider [Entity]
|
169
169
|
def valid_response?(message,
|
170
170
|
identity_provider,
|
171
|
-
**
|
171
|
+
**)
|
172
172
|
unless message.is_a?(Response)
|
173
173
|
message.errors << "not a Response object"
|
174
174
|
return false
|
175
175
|
end
|
176
176
|
|
177
177
|
message.validate(service_provider: self,
|
178
|
-
identity_provider
|
179
|
-
**
|
178
|
+
identity_provider:,
|
179
|
+
**).empty?
|
180
180
|
end
|
181
181
|
end
|
182
182
|
end
|
@@ -12,7 +12,7 @@ module SAML2
|
|
12
12
|
def initialize
|
13
13
|
super
|
14
14
|
@want_authn_requests_signed = nil
|
15
|
-
@single_sign_on_services =
|
15
|
+
@single_sign_on_services = Endpoint::Array.new
|
16
16
|
@attribute_profiles = []
|
17
17
|
@attributes = []
|
18
18
|
end
|
@@ -34,7 +34,7 @@ module SAML2
|
|
34
34
|
@want_authn_requests_signed
|
35
35
|
end
|
36
36
|
|
37
|
-
# @return [Array
|
37
|
+
# @return [Endpoint::Array]
|
38
38
|
def single_sign_on_services
|
39
39
|
@single_sign_on_services ||= load_object_array(xml, "md:SingleSignOnService", Endpoint)
|
40
40
|
end
|
data/lib/saml2/indexed_object.rb
CHANGED
@@ -4,6 +4,10 @@ require "saml2/base"
|
|
4
4
|
|
5
5
|
module SAML2
|
6
6
|
module IndexedObject
|
7
|
+
def self.included(klass)
|
8
|
+
klass.const_set(:Array, Array.dup)
|
9
|
+
end
|
10
|
+
|
7
11
|
# @return [Integer]
|
8
12
|
attr_accessor :index
|
9
13
|
|
@@ -42,9 +46,7 @@ module SAML2
|
|
42
46
|
|
43
47
|
def self.from_xml(nodes)
|
44
48
|
new(nodes.map do |node|
|
45
|
-
name.
|
46
|
-
mod.const_get(klass)
|
47
|
-
end.from_xml(node)
|
49
|
+
Object.const_get(name.rpartition("::").first, false).from_xml(node)
|
48
50
|
end).freeze
|
49
51
|
end
|
50
52
|
|
@@ -88,8 +90,14 @@ module SAML2
|
|
88
90
|
builder.parent.children.last["isDefault"] = default? if default_defined?
|
89
91
|
end
|
90
92
|
|
91
|
-
|
92
|
-
|
93
|
+
private
|
94
|
+
|
95
|
+
def indexed_object_inspect
|
96
|
+
if default_defined?
|
97
|
+
"index=#{index}, default=#{default?}"
|
98
|
+
else
|
99
|
+
"index=#{index}"
|
100
|
+
end
|
93
101
|
end
|
94
102
|
end
|
95
103
|
end
|
data/lib/saml2/logout_request.rb
CHANGED
@@ -7,15 +7,16 @@ module SAML2
|
|
7
7
|
class LogoutRequest < Request
|
8
8
|
attr_writer :name_id, :session_index
|
9
9
|
|
10
|
-
# @param sso [SSO]
|
10
|
+
# @param sso [SSO, nil]
|
11
11
|
# @param issuer [NameID]
|
12
12
|
# @param name_id [NameID]
|
13
13
|
# @param session_index optional [String, Array<String>]
|
14
|
+
# @param binding [String] the binding to use for the request
|
14
15
|
# @return [LogoutRequest]
|
15
|
-
def self.initiate(sso, issuer, name_id, session_index = [])
|
16
|
+
def self.initiate(sso, issuer, name_id, session_index = [], binding: Bindings::HTTPRedirect::URN)
|
16
17
|
logout_request = new
|
17
18
|
logout_request.issuer = issuer
|
18
|
-
logout_request.destination = sso.single_logout_services.
|
19
|
+
logout_request.destination = sso.single_logout_services.choose_endpoint(binding)&.location if sso
|
19
20
|
logout_request.name_id = name_id
|
20
21
|
logout_request.session_index = session_index
|
21
22
|
|
@@ -5,16 +5,25 @@ require "saml2/status_response"
|
|
5
5
|
module SAML2
|
6
6
|
class LogoutResponse < StatusResponse
|
7
7
|
# @param logout_request [LogoutRequest]
|
8
|
-
# @param sso [SSO]
|
8
|
+
# @param sso [SSO, nil]
|
9
9
|
# @param issuer [NameID]
|
10
10
|
# @param status_code [String]
|
11
|
+
# @param binding [String] the binding to use for the response
|
11
12
|
# @return [LogoutResponse]
|
12
|
-
def self.respond_to(logout_request,
|
13
|
+
def self.respond_to(logout_request,
|
14
|
+
sso,
|
15
|
+
issuer,
|
16
|
+
status_code = Status::SUCCESS,
|
17
|
+
binding: Bindings::HTTPRedirect::URN,
|
18
|
+
message: nil)
|
13
19
|
logout_response = new
|
14
20
|
logout_response.issuer = issuer
|
15
|
-
|
21
|
+
if sso
|
22
|
+
logout_response.destination = sso.single_logout_services.choose_endpoint(binding)&.effective_response_location
|
23
|
+
end
|
16
24
|
logout_response.in_response_to = logout_request.id
|
17
25
|
logout_response.status.code = status_code
|
26
|
+
logout_response.status.message = message
|
18
27
|
logout_response
|
19
28
|
end
|
20
29
|
|
data/lib/saml2/message.rb
CHANGED
@@ -113,13 +113,14 @@ module SAML2
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def validate
|
116
|
-
@errors = Schemas.protocol.validate(xml.document)
|
116
|
+
@errors = xml ? Schemas.protocol.validate(xml.document) : []
|
117
117
|
errors
|
118
118
|
end
|
119
119
|
|
120
120
|
# If the XML is valid according to SAML XSDs.
|
121
121
|
# @return [Boolean]
|
122
122
|
def valid_schema?
|
123
|
+
return true if xml.nil? # it didn't come from parsing XML; there's nothing to be invalid
|
123
124
|
return false unless Schemas.protocol.valid?(xml.document)
|
124
125
|
|
125
126
|
true
|
data/lib/saml2/name_id.rb
CHANGED
@@ -59,7 +59,8 @@ module SAML2
|
|
59
59
|
# @param rhs [Policy]
|
60
60
|
# @return [Boolean]
|
61
61
|
def ==(other)
|
62
|
-
|
62
|
+
other.is_a?(Policy) &&
|
63
|
+
allow_create? == other.allow_create? &&
|
63
64
|
format == other.format &&
|
64
65
|
sp_name_qualifier == other.sp_name_qualifier
|
65
66
|
end
|
@@ -102,7 +103,8 @@ module SAML2
|
|
102
103
|
# @param rhs [NameID]
|
103
104
|
# @return [Boolean]
|
104
105
|
def ==(other)
|
105
|
-
|
106
|
+
other.is_a?(NameID) &&
|
107
|
+
id == other.id &&
|
106
108
|
format == other.format &&
|
107
109
|
name_qualifier == other.name_qualifier &&
|
108
110
|
sp_name_qualifier == other.sp_name_qualifier
|
@@ -116,5 +118,18 @@ module SAML2
|
|
116
118
|
args["SPNameQualifier"] = sp_name_qualifier if sp_name_qualifier
|
117
119
|
builder["saml"].__send__(element || "NameID", id, args)
|
118
120
|
end
|
121
|
+
|
122
|
+
# @return [String]
|
123
|
+
def inspect
|
124
|
+
return id.inspect unless format || name_qualifier || sp_name_qualifier
|
125
|
+
return "#{id.inspect}@#{format.inspect}" unless name_qualifier || sp_name_qualifier
|
126
|
+
|
127
|
+
r = "#<SAML2::NameID id=#{id.inspect}"
|
128
|
+
r << " format=#{format.inspect}" if format
|
129
|
+
r << " name_qualifier=#{name_qualifier.inspect}" if name_qualifier
|
130
|
+
r << " sp_name_qualifier=#{sp_name_qualifier.inspect}" if sp_name_qualifier
|
131
|
+
r << ">"
|
132
|
+
r
|
133
|
+
end
|
119
134
|
end
|
120
135
|
end
|
data/lib/saml2/response.rb
CHANGED
@@ -35,7 +35,7 @@ module SAML2
|
|
35
35
|
end
|
36
36
|
|
37
37
|
# Begin an IdP Initiated login
|
38
|
-
# @param service_provider [ServiceProvider]
|
38
|
+
# @param service_provider [ServiceProvider, nil]
|
39
39
|
# @param issuer [NameID]
|
40
40
|
# @param name_id [NameID] The subject
|
41
41
|
# @param attributes optional [Hash<String => String>, Array<Attribute>]
|
@@ -43,7 +43,12 @@ module SAML2
|
|
43
43
|
def self.initiate(service_provider, issuer, name_id, attributes = nil)
|
44
44
|
response = new
|
45
45
|
response.issuer = issuer
|
46
|
-
|
46
|
+
if service_provider
|
47
|
+
response.destination = service_provider
|
48
|
+
.assertion_consumer_services
|
49
|
+
.choose_endpoint(Bindings::HTTP_POST::URN)
|
50
|
+
&.effective_response_location
|
51
|
+
end
|
47
52
|
assertion = Assertion.new
|
48
53
|
assertion.subject = Subject.new
|
49
54
|
assertion.subject.name_id = name_id
|
@@ -235,9 +240,9 @@ module SAML2
|
|
235
240
|
|
236
241
|
if assertion.conditions &&
|
237
242
|
!(condition_errors = assertion.conditions.validate(
|
238
|
-
verification_time
|
243
|
+
verification_time:,
|
239
244
|
audience: service_provider.entity_id,
|
240
|
-
ignore_audience_condition:
|
245
|
+
ignore_audience_condition:
|
241
246
|
)).empty?
|
242
247
|
return errors.concat(condition_errors)
|
243
248
|
end
|
data/lib/saml2/role.rb
CHANGED
@@ -44,18 +44,16 @@ module SAML2
|
|
44
44
|
|
45
45
|
# @return [Endpoint::Indexed::Array]
|
46
46
|
def assertion_consumer_services
|
47
|
-
@assertion_consumer_services ||=
|
48
|
-
|
49
|
-
|
50
|
-
end
|
47
|
+
@assertion_consumer_services ||= load_object_array(xml,
|
48
|
+
"md:AssertionConsumerService",
|
49
|
+
Endpoint::Indexed)
|
51
50
|
end
|
52
51
|
|
53
52
|
# @return [AttributeConsumingService::Array]
|
54
53
|
def attribute_consuming_services
|
55
|
-
@attribute_consuming_services ||=
|
56
|
-
|
57
|
-
|
58
|
-
end
|
54
|
+
@attribute_consuming_services ||= load_object_array(xml,
|
55
|
+
"md:AttributeConsumingService",
|
56
|
+
AttributeConsumingService)
|
59
57
|
end
|
60
58
|
|
61
59
|
# (see Base#build)
|
data/lib/saml2/signable.rb
CHANGED
@@ -100,8 +100,8 @@ module SAML2
|
|
100
100
|
#
|
101
101
|
# @param (see #validate_signature)
|
102
102
|
# @return [Boolean]
|
103
|
-
def valid_signature?(**
|
104
|
-
validate_signature(**
|
103
|
+
def valid_signature?(**)
|
104
|
+
validate_signature(**).empty?
|
105
105
|
end
|
106
106
|
|
107
107
|
# Sign this object.
|
data/lib/saml2/sso.rb
CHANGED
@@ -7,7 +7,7 @@ module SAML2
|
|
7
7
|
class SSO < Role
|
8
8
|
def initialize
|
9
9
|
super
|
10
|
-
@single_logout_services =
|
10
|
+
@single_logout_services = Endpoint::Array.new
|
11
11
|
@name_id_formats = []
|
12
12
|
end
|
13
13
|
|
@@ -18,7 +18,7 @@ module SAML2
|
|
18
18
|
@name_id_formats = nil
|
19
19
|
end
|
20
20
|
|
21
|
-
# @return [Array
|
21
|
+
# @return [Endpoint::Array]
|
22
22
|
def single_logout_services
|
23
23
|
@single_logout_services ||= load_object_array(xml, "md:SingleLogoutService", Endpoint)
|
24
24
|
end
|
data/lib/saml2/status.rb
CHANGED
@@ -4,7 +4,9 @@ require "saml2/base"
|
|
4
4
|
|
5
5
|
module SAML2
|
6
6
|
class Status < Base
|
7
|
-
SUCCESS
|
7
|
+
SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
|
8
|
+
REQUESTER = "urn:oasis:names:tc:SAML:2.0:status:Requester"
|
9
|
+
RESPONDER = "urn:oasis:names:tc:SAML:2.0:status:Responder"
|
8
10
|
|
9
11
|
# @return [String]
|
10
12
|
attr_accessor :code, :message
|
data/lib/saml2/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saml2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -70,90 +70,6 @@ dependencies:
|
|
70
70
|
- - ">="
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: 0.9.5
|
73
|
-
- !ruby/object:Gem::Dependency
|
74
|
-
name: debug
|
75
|
-
requirement: !ruby/object:Gem::Requirement
|
76
|
-
requirements:
|
77
|
-
- - "~>"
|
78
|
-
- !ruby/object:Gem::Version
|
79
|
-
version: '1.10'
|
80
|
-
type: :development
|
81
|
-
prerelease: false
|
82
|
-
version_requirements: !ruby/object:Gem::Requirement
|
83
|
-
requirements:
|
84
|
-
- - "~>"
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
version: '1.10'
|
87
|
-
- !ruby/object:Gem::Dependency
|
88
|
-
name: rake
|
89
|
-
requirement: !ruby/object:Gem::Requirement
|
90
|
-
requirements:
|
91
|
-
- - "~>"
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '13.2'
|
94
|
-
type: :development
|
95
|
-
prerelease: false
|
96
|
-
version_requirements: !ruby/object:Gem::Requirement
|
97
|
-
requirements:
|
98
|
-
- - "~>"
|
99
|
-
- !ruby/object:Gem::Version
|
100
|
-
version: '13.2'
|
101
|
-
- !ruby/object:Gem::Dependency
|
102
|
-
name: rspec
|
103
|
-
requirement: !ruby/object:Gem::Requirement
|
104
|
-
requirements:
|
105
|
-
- - "~>"
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
version: '3.5'
|
108
|
-
type: :development
|
109
|
-
prerelease: false
|
110
|
-
version_requirements: !ruby/object:Gem::Requirement
|
111
|
-
requirements:
|
112
|
-
- - "~>"
|
113
|
-
- !ruby/object:Gem::Version
|
114
|
-
version: '3.5'
|
115
|
-
- !ruby/object:Gem::Dependency
|
116
|
-
name: rubocop-inst
|
117
|
-
requirement: !ruby/object:Gem::Requirement
|
118
|
-
requirements:
|
119
|
-
- - "~>"
|
120
|
-
- !ruby/object:Gem::Version
|
121
|
-
version: '1'
|
122
|
-
type: :development
|
123
|
-
prerelease: false
|
124
|
-
version_requirements: !ruby/object:Gem::Requirement
|
125
|
-
requirements:
|
126
|
-
- - "~>"
|
127
|
-
- !ruby/object:Gem::Version
|
128
|
-
version: '1'
|
129
|
-
- !ruby/object:Gem::Dependency
|
130
|
-
name: rubocop-rake
|
131
|
-
requirement: !ruby/object:Gem::Requirement
|
132
|
-
requirements:
|
133
|
-
- - "~>"
|
134
|
-
- !ruby/object:Gem::Version
|
135
|
-
version: '0.6'
|
136
|
-
type: :development
|
137
|
-
prerelease: false
|
138
|
-
version_requirements: !ruby/object:Gem::Requirement
|
139
|
-
requirements:
|
140
|
-
- - "~>"
|
141
|
-
- !ruby/object:Gem::Version
|
142
|
-
version: '0.6'
|
143
|
-
- !ruby/object:Gem::Dependency
|
144
|
-
name: rubocop-rspec
|
145
|
-
requirement: !ruby/object:Gem::Requirement
|
146
|
-
requirements:
|
147
|
-
- - "~>"
|
148
|
-
- !ruby/object:Gem::Version
|
149
|
-
version: '3.5'
|
150
|
-
type: :development
|
151
|
-
prerelease: false
|
152
|
-
version_requirements: !ruby/object:Gem::Requirement
|
153
|
-
requirements:
|
154
|
-
- - "~>"
|
155
|
-
- !ruby/object:Gem::Version
|
156
|
-
version: '3.5'
|
157
73
|
description: |
|
158
74
|
The saml2 library is yet another SAML library for Ruby, with
|
159
75
|
an emphasis on _not_ re-implementing XML, especially XML Security,
|
@@ -237,14 +153,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
237
153
|
requirements:
|
238
154
|
- - ">="
|
239
155
|
- !ruby/object:Gem::Version
|
240
|
-
version: '2
|
156
|
+
version: '3.2'
|
241
157
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
242
158
|
requirements:
|
243
159
|
- - ">="
|
244
160
|
- !ruby/object:Gem::Version
|
245
161
|
version: '0'
|
246
162
|
requirements: []
|
247
|
-
rubygems_version: 3.
|
163
|
+
rubygems_version: 3.4.10
|
248
164
|
signing_key:
|
249
165
|
specification_version: 4
|
250
166
|
summary: SAML 2.0 Library
|