Class: Onelogin::Saml::BaseAssertion

Inherits:
Object
  • Object
show all
Defined in:
lib/onelogin/saml/base_assertion.rb

Direct Known Subclasses

LogoutRequest, LogoutResponse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#base64_assertionObject



39
40
41
42
43
44
# File 'lib/onelogin/saml/base_assertion.rb', line 39

def base64_assertion
  @base64_assertion ||= begin
    deflated_assertion = Zlib::Deflate.deflate(self.xml, 9)[2..-5]
    Base64.strict_encode64(deflated_assertion)
  end
end

#destinationObject



23
24
25
# File 'lib/onelogin/saml/base_assertion.rb', line 23

def destination
  @destination ||= root_attribute_value('Destination')
end

#idObject



11
12
13
# File 'lib/onelogin/saml/base_assertion.rb', line 11

def id
  @id ||= root_attribute_value('ID')
end

#in_response_toObject



27
28
29
# File 'lib/onelogin/saml/base_assertion.rb', line 27

def in_response_to
  @in_response_to ||= root_attribute_value('InResponseTo')
end

#issue_instantObject



15
16
17
# File 'lib/onelogin/saml/base_assertion.rb', line 15

def issue_instant
  @issue_instant ||= root_attribute_value('IssueInstance')
end

#issuerObject



19
20
21
# File 'lib/onelogin/saml/base_assertion.rb', line 19

def issuer
  @issuer ||= node_content('saml:Issuer')
end

#settingsObject

Returns the value of attribute settings.



3
4
5
# File 'lib/onelogin/saml/base_assertion.rb', line 3

def settings
  @settings
end

#xmlObject

Returns the value of attribute xml.



4
5
6
# File 'lib/onelogin/saml/base_assertion.rb', line 4

def xml
  @xml
end

Class Method Details

.generate(settings, attributes = {}) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/onelogin/saml/base_assertion.rb', line 83

def self.generate(settings, attributes = {})
  assertion = new

  assertion.settings = settings
  assertion.id = generate_unique_id
  assertion.issue_instant = get_timestamp
  assertion.issuer = settings.issuer

  attributes.each do |key, value|
    if assertion.respond_to? "#{key}="
      assertion.send "#{key}=", value
    end
  end

  assertion.xml = assertion.generate

  assertion
end

.generate_unique_id(length = 42) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/onelogin/saml/base_assertion.rb', line 137

def self.generate_unique_id(length = 42)
  chars = ("a".."f").to_a + ("0".."9").to_a
  chars_len = chars.size
  unique_id = ("a".."f").to_a[rand(6)]
  2.upto(length) { |i| unique_id << chars[rand(chars_len)] }
  unique_id
end

.get_timestampObject



145
146
147
# File 'lib/onelogin/saml/base_assertion.rb', line 145

def self.get_timestamp
  Time.new.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
end

.parse(raw_assertion, settings = nil) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/onelogin/saml/base_assertion.rb', line 60

def self.parse(raw_assertion, settings = nil)
  raise "SAML assertion too large" if raw_assertion.bytesize > Onelogin::Saml.config[:max_message_size]
  assertion = new
  assertion.base64_assertion = raw_assertion

  decoded_xml = Base64.decode64(raw_assertion)
  zlib = Zlib::Inflate.new(-Zlib::MAX_WBITS)

  xml = ''
  # do it in 1K slices, so we can protect against bombs
  (0..decoded_xml.bytesize / 1024).each do |i|
    xml.concat(zlib.inflate(decoded_xml.byteslice(i * 1024, 1024)))
    raise "SAML assertion too large" if xml.bytesize > Onelogin::Saml.config[:max_message_size]
  end
  xml.concat(zlib.finish)
  raise "SAML assertion too large" if xml.bytesize > Onelogin::Saml.config[:max_message_size]

  assertion.xml = xml

  assertion.process(settings) if settings
  assertion
end

Instance Method Details

#assertion_typeObject



46
47
48
49
50
51
52
53
54
# File 'lib/onelogin/saml/base_assertion.rb', line 46

def assertion_type
  return unless document

  if document.root.name =~ /Request$/
    :request
  elsif document.root.name =~ /Response$/
    :response
  end
end

#documentObject



31
32
33
# File 'lib/onelogin/saml/base_assertion.rb', line 31

def document
  @document ||= Nokogiri::XML(xml) if xml
end

#forward_urlObject



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/onelogin/saml/base_assertion.rb', line 102

def forward_url
  @forward_url ||= begin
    url, existing_query_string = destination.split('?')
    query_string = query_string_append(existing_query_string, query_string_param, base64_assertion)

    if settings.sign?
      query_string = query_string_append(query_string, "SigAlg", "http://www.w3.org/2000/09/xmldsig#rsa-sha1")
      signature =  generate_signature(query_string, settings.xmlsec_privatekey)
      query_string = query_string_append(query_string, "Signature", signature)
    end

    if settings.relay_state
      query_string = query_string_append(query_string, "RelayState", settings.relay_state)
    end

    [url, query_string].join("?")
  end
end

#generateObject



121
122
123
# File 'lib/onelogin/saml/base_assertion.rb', line 121

def generate
  raise "Subclass does not implement abstract method generate."
end

#node_attribute_value(xpath, attribute) ⇒ Object



129
130
131
# File 'lib/onelogin/saml/base_assertion.rb', line 129

def node_attribute_value(xpath, attribute)
  document.root.at_xpath(xpath, Onelogin::NAMESPACES)[attribute] rescue nil
end

#node_content(xpath) ⇒ Object



133
134
135
# File 'lib/onelogin/saml/base_assertion.rb', line 133

def node_content(xpath)
  document.root.at_xpath(xpath, Onelogin::NAMESPACES).content rescue nil
end

#process(settings) ⇒ Object



56
57
58
# File 'lib/onelogin/saml/base_assertion.rb', line 56

def process(settings)
  # TODO: Verify signature and decrypt.
end

#root_attribute_value(attribute) ⇒ Object



125
126
127
# File 'lib/onelogin/saml/base_assertion.rb', line 125

def root_attribute_value(attribute)
  document.root[attribute] if document
end