class OneLogin::RubySaml::Response

SAML2 Authentication Response. SAML Response

Constants

ASSERTION
DSIG
PROTOCOL
XENC

Attributes

decrypted_document[R]
document[R]
options[R]
response[R]
settings[RW]

OneLogin::RubySaml::Settings Toolkit settings

soft[RW]

Public Instance Methods

allowed_clock_drift() click to toggle source

returns the allowed clock drift on timing validation @return [Integer]

# File lib/onelogin/ruby-saml/response.rb, line 328
def allowed_clock_drift
  return options[:allowed_clock_drift] || 0
end
attributes() click to toggle source

Gets the Attributes from the AttributeStatement element.

All attributes can be iterated over attributes.each or returned as array by attributes.all For backwards compatibility ruby-saml returns by default only the first value for a given attribute with

attributes['name']

To get all of the attributes, use:

attributes.multi('name')

Or turn off the compatibility:

OneLogin::RubySaml::Attributes.single_value_compatibility = false

Now this will return an array:

attributes['name']

@return [Attributes] OneLogin::RubySaml::Attributes enumerable collection. @raise [ValidationError] if there are 2+ Attribute with the same Name

# File lib/onelogin/ruby-saml/response.rb, line 138
def attributes
  @attr_statements ||= begin
    attributes = Attributes.new

    stmt_elements = xpath_from_signed_assertion('/a:AttributeStatement')
    stmt_elements.each do |stmt_element|
      stmt_element.elements.each do |attr_element|
        if attr_element.name == "EncryptedAttribute"
          node = decrypt_attribute(attr_element.dup)
        else
          node = attr_element
        end

        name  = node.attributes["Name"]

        if options[:check_duplicated_attributes] && attributes.include?(name)
          raise ValidationError.new("Found an Attribute element with duplicated Name")
        end

        values = node.elements.collect{|e|
          if (e.elements.nil? || e.elements.size == 0)
            # SAMLCore requires that nil AttributeValues MUST contain xsi:nil XML attribute set to "true" or "1"
            # otherwise the value is to be regarded as empty.
            ["true", "1"].include?(e.attributes['xsi:nil']) ? nil : e.text.to_s
          # explicitly support saml2:NameID with saml2:NameQualifier if supplied in attributes
          # this is useful for allowing eduPersonTargetedId to be passed as an opaque identifier to use to
          # identify the subject in an SP rather than email or other less opaque attributes
          # NameQualifier, if present is prefixed with a "/" to the value
          else
           REXML::XPath.match(e,'a:NameID', { "a" => ASSERTION }).collect{|n|
              (n.attributes['NameQualifier'] ? n.attributes['NameQualifier'] +"/" : '') + n.text.to_s
            }
          end
        }

        attributes.add(name, values.flatten)
      end
    end
    attributes
  end
end
audiences() click to toggle source

@return [Array] The Audience elements from the Contitions of the SAML Response.

# File lib/onelogin/ruby-saml/response.rb, line 313
def audiences
  @audiences ||= begin
    audiences = []
    nodes = xpath_from_signed_assertion('/a:Conditions/a:AudienceRestriction/a:Audience')
    nodes.each do |node|
      if node && node.text
        audiences << node.text
      end
    end
    audiences
  end
end
conditions() click to toggle source

Gets the Condition Element of the SAML Response if exists. (returns the first node that matches the supplied xpath) @return [REXML::Element] Conditions Element if exists

# File lib/onelogin/ruby-saml/response.rb, line 234
def conditions
  @conditions ||= xpath_first_from_signed_assertion('/a:Conditions')
end
destination() click to toggle source

@return [String|nil] Destination attribute from the SAML Response.

# File lib/onelogin/ruby-saml/response.rb, line 300
def destination
  @destination ||= begin
    node = REXML::XPath.first(
      document,
      "/p:Response",
      { "p" => PROTOCOL }
    )
    node.nil? ? nil : node.attributes['Destination']
  end
end
in_response_to() click to toggle source

@return [String|nil] The InResponseTo attribute from the SAML Response.

# File lib/onelogin/ruby-saml/response.rb, line 287
def in_response_to
  @in_response_to ||= begin
    node = REXML::XPath.first(
      document,
      "/p:Response",
      { "p" => PROTOCOL }
    )
    node.nil? ? nil : node.attributes['InResponseTo']
  end
end
is_valid?(collect_errors = false) click to toggle source

Validates the SAML Response with the default values (soft = true) @param collect_errors [Boolean] Stop validation when first error appears or keep validating. (if soft=true) @return [Boolean] TRUE if the SAML Response is valid

# File lib/onelogin/ruby-saml/response.rb, line 66
def is_valid?(collect_errors = false)
  validate(collect_errors)
end
issuers() click to toggle source

Gets the Issuers (from Response and Assertion). (returns the first node that matches the supplied xpath from the Response and from the Assertion) @return [Array] Array with the Issuers (REXML::Element)

# File lib/onelogin/ruby-saml/response.rb, line 256
def issuers
  @issuers ||= begin
    issuers = []
    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)
    end

    doc = decrypted_document.nil? ? document : decrypted_document
    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)
    end

    nodes = issuer_response_nodes + issuer_assertion_nodes
    nodes.each do |node|
      issuers << node.text if node.text
    end
    issuers.uniq
  end
end
name_id() click to toggle source

@return [String] the NameID provided by the SAML response from the IdP.

# File lib/onelogin/ruby-saml/response.rb, line 72
def name_id
  @name_id ||=
    if name_id_node
      name_id_node.text
    end
end
Also aliased as: nameid
name_id_format() click to toggle source

@return [String] the NameID Format provided by the SAML response from the IdP.

# File lib/onelogin/ruby-saml/response.rb, line 83
def name_id_format
  @name_id_format ||=
    if name_id_node && name_id_node.attribute("Format")
      name_id_node.attribute("Format").value
    end
end
Also aliased as: nameid_format
name_id_namequalifier() click to toggle source

@return [String] the NameID NameQualifier provided by the SAML response from the IdP.

# File lib/onelogin/ruby-saml/response.rb, line 103
def name_id_namequalifier
  @name_id_namequalifier ||=
    if name_id_node && name_id_node.attribute("NameQualifier")
      name_id_node.attribute("NameQualifier").value
    end
end
name_id_spnamequalifier() click to toggle source

@return [String] the NameID SPNameQualifier provided by the SAML response from the IdP.

# File lib/onelogin/ruby-saml/response.rb, line 94
def name_id_spnamequalifier
  @name_id_spnamequalifier ||=
    if name_id_node && name_id_node.attribute("SPNameQualifier")
      name_id_node.attribute("SPNameQualifier").value
    end
end
nameid() click to toggle source
Alias for: name_id
nameid_format() click to toggle source
Alias for: name_id_format
not_before() click to toggle source

Gets the NotBefore Condition Element value. @return [Time] The NotBefore value in Time format

# File lib/onelogin/ruby-saml/response.rb, line 241
def not_before
  @not_before ||= parse_time(conditions, "NotBefore")
end
not_on_or_after() click to toggle source

Gets the NotOnOrAfter Condition Element value. @return [Time] The NotOnOrAfter value in Time format

# File lib/onelogin/ruby-saml/response.rb, line 248
def not_on_or_after
  @not_on_or_after ||= parse_time(conditions, "NotOnOrAfter")
end
session_expires_at() click to toggle source

Gets the SessionNotOnOrAfter from the AuthnStatement. Could be used to set the local session expiration (expire at latest) @return [String] The SessionNotOnOrAfter value

# File lib/onelogin/ruby-saml/response.rb, line 184
def session_expires_at
  @expires_at ||= begin
    node = xpath_first_from_signed_assertion('/a:AuthnStatement')
    node.nil? ? nil : parse_time(node, "SessionNotOnOrAfter")
  end
end
sessionindex() click to toggle source

Gets the SessionIndex from the AuthnStatement. Could be used to be stored in the local session in order to be used in a future Logout Request that the SP could send to the IdP, to set what specific session must be deleted @return [String] SessionIndex Value

# File lib/onelogin/ruby-saml/response.rb, line 116
def sessionindex
  @sessionindex ||= begin
    node = xpath_first_from_signed_assertion('/a:AuthnStatement')
    node.nil? ? nil : node.attributes['SessionIndex']
  end
end
status_code() click to toggle source

@return [String] StatusCode value from a SAML Response.

# File lib/onelogin/ruby-saml/response.rb, line 200
def status_code
  @status_code ||= begin
    nodes = REXML::XPath.match(
      document,
      "/p:Response/p:Status/p:StatusCode",
      { "p" => PROTOCOL }
    )
    if nodes.size == 1
      node = nodes[0]
      node.attributes["Value"] if node && node.attributes
    end
  end
end
status_message() click to toggle source

@return [String] the StatusMessage value from a SAML Response.

# File lib/onelogin/ruby-saml/response.rb, line 216
def status_message
  @status_message ||= begin
    nodes = REXML::XPath.match(
      document,
      "/p:Response/p:Status/p:StatusMessage",
      { "p" => PROTOCOL }
    )
    if nodes.size == 1
      node = nodes[0]
      node.text if node
    end
  end
end
success?() click to toggle source

Checks if the Status has the “Success” code @return [Boolean] True if the StatusCode is Sucess

# File lib/onelogin/ruby-saml/response.rb, line 194
def success?
  status_code == "urn:oasis:names:tc:SAML:2.0:status:Success"
end

Public Class Methods

new(response, options = {}) click to toggle source

Constructs the SAML Response. A Response Object that is an extension of the SamlMessage class. @param response [String] A UUEncoded SAML response from the IdP. @param options [Hash] :settings to provide the OneLogin::RubySaml::Settings object

Or some options for the response validation process like skip the conditions validation
with the :skip_conditions, or allow a clock_drift when checking dates with :allowed_clock_drift
or :matches_request_id that will validate that the response matches the ID of the request,
or skip the subject confirmation validation with the :skip_subject_confirmation option
# File lib/onelogin/ruby-saml/response.rb, line 40
def initialize(response, options = {})
  raise ArgumentError.new("Response cannot be nil") if response.nil?

  @errors = []

  @options = options
  @soft = true
  unless options[:settings].nil?
    @settings = options[:settings]
    unless @settings.soft.nil?
      @soft = @settings.soft
    end
  end

  @response = decode_raw_saml(response)
  @document = XMLSecurity::SignedDocument.new(@response, @errors)

  if assertion_encrypted?
    @decrypted_document = generate_decrypted_document
  end
end