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.



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

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

Instance Attribute Details

#destinationString?

Returns:

  • (String, nil)


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

def destination
  @destination = xml["Destination"] if xml && !instance_variable_defined?(:@destination)
  @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:



157
158
159
# File 'lib/saml2/message.rb', line 157

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
66
67
# File 'lib/saml2/message.rb', line 60

def from_xml(node)
  return super unless self == Message

  klass = Message.known_messages[node.name]
  raise UnknownMessage, "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.



76
77
78
79
80
81
82
83
84
85
86
# File 'lib/saml2/message.rb', line 76

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

  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)


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

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

#idString

Returns:

  • (String)


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

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

#issue_instantTime

Returns:

  • (Time)


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

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)


129
130
131
132
133
134
135
136
137
138
# File 'lib/saml2/message.rb', line 129

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)


122
123
124
125
126
# File 'lib/saml2/message.rb', line 122

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

  true
end

#validateObject



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

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