Class: Samlsso::Response

Inherits:
SamlMessage show all
Defined in:
lib/samlsso/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

Methods inherited from SamlMessage

schema, #valid_saml?, #validation_error

Constructor Details

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

Returns a new instance of Response.

Raises:

  • (ArgumentError)


24
25
26
27
28
29
30
31
32
33
# File 'lib/samlsso/response.rb', line 24

def initialize(response, options = {})
  @errors = []
  raise ArgumentError.new("Response cannot be nil") if response.nil?
  @options  = options
  @decoded_response = decode_raw_saml(response)
  @decrypted_response = decrypt_saml(@decoded_response, @options[:private_key_file_path])
  @response = @decrypted_response
  @document = XMLSecurity::SignedDocument.new(@response, @errors)
  @decoded_document = XMLSecurity::SignedDocument.new(@decoded_response, @errors)
end

Instance Attribute Details

#decoded_documentObject (readonly)

Returns the value of attribute decoded_document.



22
23
24
# File 'lib/samlsso/response.rb', line 22

def decoded_document
  @decoded_document
end

#decoded_responseObject (readonly)

Returns the value of attribute decoded_response.



20
21
22
# File 'lib/samlsso/response.rb', line 20

def decoded_response
  @decoded_response
end

#decrypted_responseObject (readonly)

Returns the value of attribute decrypted_response.



21
22
23
# File 'lib/samlsso/response.rb', line 21

def decrypted_response
  @decrypted_response
end

#documentObject (readonly)

Returns the value of attribute document.



19
20
21
# File 'lib/samlsso/response.rb', line 19

def document
  @document
end

#errorsObject

Returns the value of attribute errors.



15
16
17
# File 'lib/samlsso/response.rb', line 15

def errors
  @errors
end

#optionsObject (readonly)

Returns the value of attribute options.



17
18
19
# File 'lib/samlsso/response.rb', line 17

def options
  @options
end

#responseObject (readonly)

Returns the value of attribute response.



18
19
20
# File 'lib/samlsso/response.rb', line 18

def response
  @response
end

#settingsObject

TODO: This should probably be ctor initialized too… WDYT?



14
15
16
# File 'lib/samlsso/response.rb', line 14

def settings
  @settings
end

Instance Method Details

#attributesObject

Returns Samlsso::Attributes enumerable collection. All attributes can be iterated over attributes.each or returned as array by attributes.all

For backwards compatibility samlsso 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:

Samlsso::Attributes.single_value_compatibility = false

Now this will return an array:

attributes['name']


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/samlsso/response.rb', line 73

def attributes
  @attr_statements ||= begin
    attributes = Attributes.new

    stmt_element = xpath_first_from_signed_assertion('/a:AttributeStatement')
    return attributes if stmt_element.nil?

    stmt_element.elements.each do |attr_element|
      name  = attr_element.attributes["Name"] ? attr_element.attributes["Name"] : attr_element.attributes["name"]
      values = attr_element.elements.collect{|e|
        # 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
      }

      attributes.add(name, values)
    end

    attributes
  end
end

#conditionsObject

Conditions (if any) for the assertion to run



119
120
121
# File 'lib/samlsso/response.rb', line 119

def conditions
  @conditions ||= xpath_first_from_signed_assertion('/a:Conditions')
end

#is_valid?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/samlsso/response.rb', line 35

def is_valid?
  validate
end

#issuerObject



131
132
133
134
135
136
137
# File 'lib/samlsso/response.rb', line 131

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

#name_idObject

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



48
49
50
51
52
53
# File 'lib/samlsso/response.rb', line 48

def name_id
  @name_id ||= begin
    node = xpath_first_from_signed_assertion('/a:Subject/a:NameID')
    node.nil? ? nil : node.text
  end
end

#not_beforeObject



123
124
125
# File 'lib/samlsso/response.rb', line 123

def not_before
  @not_before ||= parse_time(conditions, "NotBefore")
end

#not_on_or_afterObject



127
128
129
# File 'lib/samlsso/response.rb', line 127

def not_on_or_after
  @not_on_or_after ||= parse_time(conditions, "NotOnOrAfter")
end

#session_expires_atObject

When this user session should expire at latest



96
97
98
99
100
101
# File 'lib/samlsso/response.rb', line 96

def session_expires_at
  @expires_at ||= begin
    node = xpath_first_from_signed_assertion('/a:AuthnStatement')
    parse_time(node, "SessionNotOnOrAfter")
  end
end

#sessionindexObject



55
56
57
58
59
60
# File 'lib/samlsso/response.rb', line 55

def sessionindex
  @sessionindex ||= begin
    node = xpath_first_from_signed_assertion('/a:AuthnStatement')
    node.nil? ? nil : (node.attributes['SessionIndex'] ? node.attributes['SessionIndex'] : node.attributes['sessionindex'])
  end
end

#status_messageObject



111
112
113
114
115
116
# File 'lib/samlsso/response.rb', line 111

def status_message
  @status_message ||= begin
    node = REXML::XPath.first(document, "/p:Response/p:Status/p:StatusMessage", { "p" => PROTOCOL, "a" => ASSERTION })
    node.text if node
  end
end

#success?Boolean

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

Returns:

  • (Boolean)


104
105
106
107
108
109
# File 'lib/samlsso/response.rb', line 104

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" || node.attributes["value"] == "urn:oasis:names:tc:SAML:2.0:status:Success"
  end
end

#validate!Object



39
40
41
# File 'lib/samlsso/response.rb', line 39

def validate!
  validate(false)
end