Skip to content

Commit 1108d80

Browse files
committed
handle XSW case
1 parent d8ba3da commit 1108d80

File tree

2 files changed

+51
-31
lines changed

2 files changed

+51
-31
lines changed

lib/samlr/assertion.rb

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Samlr
22
class Assertion
3+
DEFAULT_LOCATION = "/samlp:Response/saml:Assertion"
34
attr_reader :document, :options
45

56
def initialize(document, options)
@@ -8,38 +9,47 @@ def initialize(document, options)
89
end
910

1011
def verify!
11-
verify_assertion!
12+
verify_signature!
1213
verify_conditions! unless skip_conditions?
13-
signature.verify! unless signature.missing?
1414

1515
true
1616
end
1717

1818
def location
19-
"/samlp:Response/saml:Assertion"
19+
@location ||= begin
20+
verify_signature!
21+
22+
if !signature.missing?
23+
if signature.references.any?
24+
"//saml:Assertion[@ID='#{signature.references.first.uri}']"
25+
else
26+
raise SignatureError.new("Missing references inside checked signature")
27+
end
28+
else
29+
DEFAULT_LOCATION
30+
end
31+
end
2032
end
2133

2234
def signature
23-
@signature ||= Samlr::Signature.new(document, location, options)
35+
@signature ||= Samlr::Signature.new(document, DEFAULT_LOCATION, options)
2436
end
2537

2638
def attributes
27-
@attributes ||= begin
28-
{}.tap do |attrs|
29-
assertion.xpath("./saml:AttributeStatement/saml:Attribute", NS_MAP).each do |statement|
30-
name = statement["Name"]
31-
values = statement.xpath("./saml:AttributeValue", NS_MAP)
32-
33-
if values.size == 0
34-
next
35-
elsif values.size == 1
36-
value = values.first.text
37-
else
38-
value = values.map { |value| value.text }
39-
end
40-
41-
attrs[name] = attrs[name.to_sym] = value
39+
@attributes ||= {}.tap do |attrs|
40+
assertion.xpath("./saml:AttributeStatement/saml:Attribute", NS_MAP).each do |statement|
41+
name = statement["Name"]
42+
values = statement.xpath("./saml:AttributeValue", NS_MAP)
43+
44+
if values.size == 0
45+
next
46+
elsif values.size == 1
47+
value = values.first.text
48+
else
49+
value = values.map { |value| value.text }
4250
end
51+
52+
attrs[name] = attrs[name.to_sym] = value
4353
end
4454
end
4555
end
@@ -54,6 +64,13 @@ def assertion
5464
@assertion ||= document.at(location, NS_MAP)
5565
end
5666

67+
def verify_signature!
68+
verify_assertion!
69+
signature.verify! unless signature.missing?
70+
71+
true
72+
end
73+
5774
def skip_conditions?
5875
!!options[:skip_conditions]
5976
end
@@ -67,7 +84,7 @@ def verify_conditions!
6784
end
6885

6986
def verify_assertion!
70-
assertion_count = document.xpath(location, NS_MAP).size
87+
assertion_count = document.xpath(DEFAULT_LOCATION, NS_MAP).size
7188

7289
if assertion_count == 0
7390
raise Samlr::FormatError.new("Invalid SAML response: assertion missing")

lib/samlr/signature.rb

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def initialize(original, prefix, options)
1515
@document = original.dup
1616
@prefix = prefix
1717
@options = options
18+
@verified = false
1819

1920
if @signature = document.at("#{prefix}/ds:Signature", NS_MAP)
2021
@signature.remove # enveloped signatures only
@@ -35,14 +36,26 @@ def missing?
3536
signature.nil?
3637
end
3738

39+
def verified?
40+
@verified
41+
end
42+
3843
def verify!
3944
raise SignatureError.new("No signature at #{prefix}/ds:Signature") unless present?
4045

4146
verify_fingerprint! unless options[:skip_fingerprint]
4247
verify_digests!
4348
verify_signature!
4449

45-
true
50+
@verified = true
51+
end
52+
53+
def references
54+
@references ||= [].tap do |refs|
55+
original.xpath("#{prefix}/ds:Signature/ds:SignedInfo/ds:Reference[@URI]", NS_MAP).each do |ref|
56+
refs << Samlr::Reference.new(ref)
57+
end
58+
end
4659
end
4760

4861
private
@@ -90,16 +103,6 @@ def referenced_node(id)
90103
nodes.first
91104
end
92105

93-
def references
94-
@references ||= begin
95-
[].tap do |refs|
96-
original.xpath("#{prefix}/ds:Signature/ds:SignedInfo/ds:Reference[@URI]", NS_MAP).each do |ref|
97-
refs << Samlr::Reference.new(ref)
98-
end
99-
end
100-
end
101-
end
102-
103106
def signature_method
104107
@signature_method ||= Samlr::Tools.algorithm(signature.at("./ds:SignedInfo/ds:SignatureMethod/@Algorithm", NS_MAP).try(:value))
105108
end

0 commit comments

Comments
 (0)