Class: SAML2::Message Abstract

Inherits:
Base
  • Object
show all
Includes:
Signable
Defined in:
lib/saml2/message.rb

Overview

This class is abstract.

In the SAML Schema, Request and Response don’t technically share a common ancestor, but they have several things in common so it’s useful to represent that in this gem as a common base class.

Direct Known Subclasses

Assertion, Request, StatusResponse

Instance Attribute Summary collapse

Attributes inherited from Base

#xml

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Signable

#signature, #signed?, #signing_key, #valid_signature?, #validate_signature

Methods inherited from Base

#decrypt, #inspect, load_object_array, load_string_array, lookup_qname, #to_s, #to_xml

Constructor Details

#initializeMessage

Returns a new instance of Message.



95
96
97
98
99
100
# File 'lib/saml2/message.rb', line 95

def initialize
  super
  @errors = []
  @id = "_#{SecureRandom.uuid}"
  @issue_instant = Time.now.utc
end

Instance Attribute Details

#destinationString?

Returns:

  • (String, nil)


145
146
147
148
149
150
# File 'lib/saml2/message.rb', line 145

def destination
  if xml && !instance_variable_defined?(:@destination)
    @destination = xml['Destination']
  end
  @destination
end

#errorsObject (readonly)

Returns the value of attribute errors.



47
48
49
# File 'lib/saml2/message.rb', line 47

def errors
  @errors
end

#issuerNameID?

Returns:



153
154
155
# File 'lib/saml2/message.rb', line 153

def issuer
  @issuer ||= NameID.from_xml(xml.at_xpath('saml:Issuer', Namespaces::ALL))
end

Class Method Details

.from_xml(node) ⇒ Message

Create an appropriate SAML2::Message subclass instance to represent the given XML element.

When called on a subclass, it behaves the same as Base.from_xml

Parameters:

  • node (Nokogiri::XML::Element)

Returns:

Raises:

  • (UnknownMessage)

    If the element doesn’t correspond to a known SAML message type.



60
61
62
63
64
65
# File 'lib/saml2/message.rb', line 60

def from_xml(node)
  return super unless self == Message
  klass = Message.known_messages[node.name]
  raise UnknownMessage.new("Unknown message #{node.name}") unless klass
  klass.from_xml(node)
end

.parse(xml) ⇒ Message

Parses XML, and returns an appropriate SAML2::Message subclass instance.

Parameters:

  • xml (String, IO)

    Anything that can be passed to Nokogiri::XML.

Returns:

Raises:

  • (UnexpectedMessage)

    If called on a subclass, will raise if the parsed message does not match the class is was called on.



74
75
76
77
78
79
80
# File 'lib/saml2/message.rb', line 74

def parse(xml)
  result = Message.from_xml(Nokogiri::XML(xml) { |config| config.strict }.root)
  raise UnexpectedMessage.new("Expected a #{self.name}, but got a #{result.class.name}") unless self == Message || result.class == self
  result
rescue Nokogiri::XML::SyntaxError
  raise CorruptMessage
end

Instance Method Details

#from_xml(node) ⇒ void

This method returns an undefined value.

Parse an XML element into this object.

Parameters:

  • node (Nokogiri::XML::Element)


103
104
105
106
107
# File 'lib/saml2/message.rb', line 103

def from_xml(node)
  super
  @id = nil
  @issue_instant = nil
end

#idString

Returns:

  • (String)


135
136
137
# File 'lib/saml2/message.rb', line 135

def id
  @id ||= xml['ID']
end

#issue_instantTime

Returns:

  • (Time)


140
141
142
# File 'lib/saml2/message.rb', line 140

def issue_instant
  @issue_instant ||= Time.parse(xml['IssueInstant'])
end

#sign(x509_certificate, private_key, algorithm_name = :sha256) ⇒ self

Sign this object.

Parameters:

  • x509_certificate (String)

    The certificate corresponding to private_key, to be embedded in the signature.

  • private_key (String)

    The key to use to sign.

  • algorithm_name (Symbol) (defaults to: :sha256)

Returns:

  • (self)


123
124
125
126
127
128
129
130
131
132
# File 'lib/saml2/message.rb', line 123

def sign(x509_certificate, private_key, algorithm_name = :sha256)
  super

  xml = @document.root
  # the Signature element must be right after the Issuer, so put it there
  issuer = xml.at_xpath("saml:Issuer", Namespaces::ALL)
  signature = xml.at_xpath("dsig:Signature", Namespaces::ALL)
  issuer.add_next_sibling(signature)
  self
end

#valid_schema?Boolean

If the XML is valid according to SAML XSDs.

Returns:

  • (Boolean)


116
117
118
119
120
# File 'lib/saml2/message.rb', line 116

def valid_schema?
  return false unless Schemas.protocol.valid?(xml.document)

  true
end

#validateObject



109
110
111
112
# File 'lib/saml2/message.rb', line 109

def validate
  @errors = Schemas.protocol.validate(xml.document)
  errors
end