Skip to content

Commit a3d9d8c

Browse files
committed
Add support on LogoutRequest with Encrypted NameID
1 parent 5193314 commit a3d9d8c

1 file changed

Lines changed: 39 additions & 7 deletions

File tree

lib/onelogin/ruby-saml/slo_logoutrequest.rb

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,26 +62,58 @@ def is_valid?(collect_errors = false)
6262
# @return [String] Gets the NameID of the Logout Request.
6363
#
6464
def name_id
65-
@name_id ||= begin
66-
node = REXML::XPath.first(document, "/p:LogoutRequest/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
67-
Utils.element_text(node)
68-
end
65+
@name_id ||= Utils.element_text(name_id_node)
6966
end
7067

7168
alias_method :nameid, :name_id
7269

7370
# @return [String] Gets the NameID Format of the Logout Request.
7471
#
7572
def name_id_format
76-
@name_id_node ||= REXML::XPath.first(document, "/p:LogoutRequest/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
7773
@name_id_format ||=
78-
if @name_id_node && @name_id_node.attribute("Format")
79-
@name_id_node.attribute("Format").value
74+
if name_id_node && name_id_node.attribute("Format")
75+
name_id_node.attribute("Format").value
8076
end
8177
end
8278

8379
alias_method :nameid_format, :name_id_format
8480

81+
def name_id_node
82+
@name_id_node ||=
83+
begin
84+
encrypted_node = REXML::XPath.first(document, "/p:LogoutRequest/a:EncryptedID", { "p" => PROTOCOL, "a" => ASSERTION })
85+
if encrypted_node
86+
node = decrypt_nameid(encrypted_node)
87+
else
88+
node = REXML::XPath.first(document, "/p:LogoutRequest/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
89+
end
90+
end
91+
end
92+
93+
# Decrypts an EncryptedID element
94+
# @param encryptedid_node [REXML::Element] The EncryptedID element
95+
# @return [REXML::Document] The decrypted EncrypedtID element
96+
#
97+
def decrypt_nameid(encrypt_node)
98+
99+
if settings.nil? || !settings.get_sp_key
100+
raise ValidationError.new('An ' + encrypt_node.name + ' found and no SP private key found on the settings to decrypt it')
101+
end
102+
103+
node_header = '<node xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">'
104+
105+
elem_plaintext = OneLogin::RubySaml::Utils.decrypt_data(encrypt_node, settings.get_sp_key)
106+
# If we get some problematic noise in the plaintext after decrypting.
107+
# This quick regexp parse will grab only the Element and discard the noise.
108+
elem_plaintext = elem_plaintext.match(/(.*<\/(\w+:)?NameID>)/m)[0]
109+
110+
# To avoid namespace errors if saml namespace is not defined
111+
# create a parent node first with the namespace defined
112+
elem_plaintext = node_header + elem_plaintext + '</node>'
113+
doc = REXML::Document.new(elem_plaintext)
114+
doc.root[0]
115+
end
116+
85117
# @return [String|nil] Gets the ID attribute from the Logout Request. if exists.
86118
#
87119
def id

0 commit comments

Comments
 (0)