Class: Spid::Saml::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/spid/ruby-saml/response.rb

Constant Summary collapse

ASSERTION =
"urn:oasis:names:tc:SAML:2.0:assertion"
PROTOCOL =
"urn:oasis:names:tc:SAML:2.0:protocol"
DSIG =
"http://www.w3.org/2000/09/xmldsig#"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(response, options = {}) ⇒ Response

Returns a new instance of Response.

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/spid/ruby-saml/response.rb', line 22

def initialize(response, options = {})
  raise ArgumentError.new("Response cannot be nil") if response.nil?
  self.options  = options
  self.response = response
  if assertion_encrypted?
    @decrypted_document = generate_decrypted_document
  end
  begin
    self.document = Spid::XMLSecurityNew::SignedDocument.new(Base64.decode64(response))
  rescue REXML::ParseException => e
    if response =~ /</
      self.document = Spid::XMLSecurityNew::SignedDocument.new(response)
    else
      raise e
    end
  end
  
end

Instance Attribute Details

#attr_name_formatObject

Returns the value of attribute attr_name_format.



18
19
20
# File 'lib/spid/ruby-saml/response.rb', line 18

def attr_name_format
  @attr_name_format
end

#decrypted_documentObject (readonly)

Returns the value of attribute decrypted_document.



19
20
21
# File 'lib/spid/ruby-saml/response.rb', line 19

def decrypted_document
  @decrypted_document
end

#documentObject

Returns the value of attribute document.



18
19
20
# File 'lib/spid/ruby-saml/response.rb', line 18

def document
  @document
end

#optionsObject

Returns the value of attribute options.



18
19
20
# File 'lib/spid/ruby-saml/response.rb', line 18

def options
  @options
end

#responseObject

Returns the value of attribute response.



18
19
20
# File 'lib/spid/ruby-saml/response.rb', line 18

def response
  @response
end

#settingsObject

Returns the value of attribute settings.



18
19
20
# File 'lib/spid/ruby-saml/response.rb', line 18

def settings
  @settings
end

Instance Method Details

#assertion_authninstantObject

ricavo l’issue instant della request



239
240
241
242
# File 'lib/spid/ruby-saml/response.rb', line 239

def assertion_authninstant
  node_authn_statement = xpath_first_from_signed_assertion('/a:AuthnStatement')
  return  node_authn_statement.attributes["AuthnInstant"] unless node_authn_statement.blank?
end

#assertion_conditions_not_beforeObject



228
229
230
231
# File 'lib/spid/ruby-saml/response.rb', line 228

def assertion_conditions_not_before
  node_cond_not_before = xpath_first_from_signed_assertion('/a:Conditions')
  return  node_cond_not_before.attributes["NotBefore"] unless node_cond_not_before.blank?
end

#assertion_conditions_not_on_or_afterObject



233
234
235
236
# File 'lib/spid/ruby-saml/response.rb', line 233

def assertion_conditions_not_on_or_after
  node_cond_not_on_or_after = xpath_first_from_signed_assertion('/a:Conditions')
  return  node_cond_not_on_or_after.attributes["NotOnOrAfter"] unless node_cond_not_on_or_after.blank?
end

#assertion_encrypted?Boolean

Checks if the SAML Response contains or not an EncryptedAssertion element

Returns:

  • (Boolean)

    True if the SAML Response contains an EncryptedAssertion element



44
45
46
47
# File 'lib/spid/ruby-saml/response.rb', line 44

def assertion_encrypted?
  false
  #!REXML::XPath.first(self.document, "(/p:Response/EncryptedAssertion/)|(/p:Response/a:EncryptedAssertion/)", { "p" => PROTOCOL, "a" => ASSERTION }).nil?
end

#assertion_idObject



208
209
210
211
# File 'lib/spid/ruby-saml/response.rb', line 208

def assertion_id
  node = REXML::XPath.first(document, "/p:Response/a:Assertion/", { "p" => PROTOCOL, "a" => ASSERTION  })
  return  node.attributes["ID"] unless node.blank?
end

#assertion_issue_instantObject



203
204
205
206
# File 'lib/spid/ruby-saml/response.rb', line 203

def assertion_issue_instant
  node = REXML::XPath.first(document, "/p:Response/a:Assertion/", { "p" => PROTOCOL, "a" => ASSERTION  })
  return  node.attributes["IssueInstant"] unless node.blank?
end

#assertion_present?Boolean

Returns:

  • (Boolean)


198
199
200
201
# File 'lib/spid/ruby-saml/response.rb', line 198

def assertion_present?
  node = REXML::XPath.first(document, "/p:Response/a:Assertion/", { "p" => PROTOCOL, "a" => ASSERTION  })
  return  !node.blank?
end

#assertion_subjectObject



213
214
215
216
# File 'lib/spid/ruby-saml/response.rb', line 213

def assertion_subject
  node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION  })
  return  node.text
end

#assertion_subject_confirmation_data_not_on_or_afterObject



223
224
225
226
# File 'lib/spid/ruby-saml/response.rb', line 223

def assertion_subject_confirmation_data_not_on_or_after
  node_subj_conf_data = xpath_first_from_signed_assertion('/a:Subject/a:SubjectConfirmation/a:SubjectConfirmationData')
  return  node_subj_conf_data.attributes["NotOnOrAfter"] unless node_subj_conf_data.blank?
end

#assertion_subject_name_qualifierObject



218
219
220
221
# File 'lib/spid/ruby-saml/response.rb', line 218

def assertion_subject_name_qualifier
  node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION  })
  return  node.attributes["NameQualifier"] unless node.blank?
end

#attributesObject

A hash of alle the attributes with the response. Assuming there is only one value for each key



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/spid/ruby-saml/response.rb', line 70

def attributes
  @attr_statements ||= begin
    result = {}
    stmt_element = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AttributeStatement", { "p" => PROTOCOL, "a" => ASSERTION })
    return {} if stmt_element.nil?
    
    @attr_name_format = []
    stmt_element.elements.each do |attr_element|
      name  = attr_element.attributes["Name"]
      #salvo i vari format per controllare poi che non ce ne siano di null
      @attr_name_format << attr_element.attributes["NameFormat"].blank? ? nil : attr_element.attributes["NameFormat"].text
      value = (attr_element.elements.blank? ? nil : attr_element.elements.first.text)

      result[name] = value
    end
    #mette il symbol
    result.keys.each do |key|
      result[key.intern] = result[key]
    end

    result
  end
end

#conditionsObject

Conditions (if any) for the assertion to run



119
120
121
122
123
# File 'lib/spid/ruby-saml/response.rb', line 119

def conditions
  @conditions ||= begin
    REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id}']/a:Conditions", { "p" => PROTOCOL, "a" => ASSERTION })
  end
end

#get_status_messageObject

Ritorno il valore dello StatusMessage



113
114
115
116
# File 'lib/spid/ruby-saml/response.rb', line 113

def get_status_message
    node = REXML::XPath.first(document, "/p:Response/p:Status/p:StatusMessage", { "p" => PROTOCOL, "a" => ASSERTION })
    node.text unless node.blank?
end

#idObject



188
189
190
191
# File 'lib/spid/ruby-saml/response.rb', line 188

def id
  node = REXML::XPath.first(document, "/p:Response", { "p" => PROTOCOL })
  return  node.attributes["ID"] unless node.blank?
end

#is_valid?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/spid/ruby-saml/response.rb', line 49

def is_valid?
  validate
end

#issue_instantObject



193
194
195
196
# File 'lib/spid/ruby-saml/response.rb', line 193

def issue_instant
  node = REXML::XPath.first(document, "/p:Response", { "p" => PROTOCOL })
  return  node.attributes["IssueInstant"] unless node.blank?
end

#issuerObject



130
131
132
133
134
135
136
# File 'lib/spid/ruby-saml/response.rb', line 130

def issuer
  @issuer ||= begin
    node = REXML::XPath.first(document, "/p:Response/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
    node ||= REXML::XPath.first(document, "/p:Response/a:Assertion/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
    node.nil? ? nil : node.text
  end
end

#issuers(soft = true) ⇒ Array

Gets the Issuers (from Response and Assertion). (returns the first node that matches the supplied xpath from the Response and from the Assertion)

Returns:

  • (Array)

    Array with the Issuers (REXML::Element)



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/spid/ruby-saml/response.rb', line 142

def issuers(soft=true)
  @issuers ||= begin
    issuer_response_nodes = REXML::XPath.match(
      document,
      "/p:Response/a:Issuer",
      { "p" => PROTOCOL, "a" => ASSERTION }
    )

    unless issuer_response_nodes.size == 1
      # error_msg = "Issuer of the Response not found or multiple."
      # raise ValidationError.new(error_msg)
      return (soft ? false : validation_error("Issuer of the Response not found or multiple."))
    end

    issuer_assertion_nodes = xpath_from_signed_assertion("/a:Issuer")
    unless issuer_assertion_nodes.size == 1
      # error_msg = "Issuer of the Assertion not found or multiple."
      # raise ValidationError.new(error_msg)
      return (soft ? false : validation_error("Issuer of the Assertion not found or multiple."))
    end

    issuer_response_nodes.each{ |iss|
      #controllo: L'attributo Format di Issuer deve essere presente con il valore urn:oasis:names:tc:SAML:2.0:nameid-format:entity
      return (soft ? false : validation_error("Elemento Issuer non ha formato corretto ")) if !iss.attributes['Format'].nil? && iss.attributes['Format'] != 'urn:oasis:names:tc:SAML:2.0:nameid-format:entity'

    }

    issuer_assertion_nodes.each{ |iss|
      #controllo: L'attributo Format di Issuer deve essere presente con il valore urn:oasis:names:tc:SAML:2.0:nameid-format:entity
      return (soft ? false : validation_error("Elemento Issuer non ha formato corretto ")) if iss.attributes['Format'] != 'urn:oasis:names:tc:SAML:2.0:nameid-format:entity'

    }

    nodes = issuer_response_nodes + issuer_assertion_nodes

    nodes.map { |node| Utils.element_text(node) }.compact.uniq
  end
end

#name_idObject

The value of the user identifier as designated by the initialization request response



58
59
60
61
62
63
64
# File 'lib/spid/ruby-saml/response.rb', line 58

def name_id
  @name_id ||= begin
    node = REXML::XPath.first(document, "/saml2p:Response/saml2:Assertion[@ID='#{document.signed_element_id}']/saml2:Subject/saml2:NameID")
    node ||=  REXML::XPath.first(document, "/saml2p:Response[@ID='#{document.signed_element_id}']/saml2:Assertion/saml2:Subject/saml2:NameID")
    node.nil? ? nil : node.text
  end
end

#response_to_idObject



183
184
185
186
# File 'lib/spid/ruby-saml/response.rb', line 183

def response_to_id
  node = REXML::XPath.first(document, "/p:Response", { "p" => PROTOCOL })
  return  node.attributes["InResponseTo"] unless node.blank?
end

#session_expires_atObject

When this user session should expire at latest



95
96
97
98
99
100
# File 'lib/spid/ruby-saml/response.rb', line 95

def session_expires_at
  @expires_at ||= begin
    node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AuthnStatement", { "p" => PROTOCOL, "a" => ASSERTION })
    parse_time(node, "SessionNotOnOrAfter")
  end
end

#success?Boolean

Checks the status of the response for a “Success” code

Returns:

  • (Boolean)


105
106
107
108
109
110
# File 'lib/spid/ruby-saml/response.rb', line 105

def success?
  @status_code ||= begin
    node = REXML::XPath.first(document, "/p:Response/p:Status/p:StatusCode", { "p" => PROTOCOL, "a" => ASSERTION })
    node.attributes["Value"] == "urn:oasis:names:tc:SAML:2.0:status:Success" unless node.blank?
  end
end

#validate!Object



53
54
55
# File 'lib/spid/ruby-saml/response.rb', line 53

def validate!
  validate(false)
end