ruby-saml 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-saml might be problematic. Click here for more details.

data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.4.0
@@ -3,17 +3,15 @@ require "time"
3
3
 
4
4
  module Onelogin::Saml
5
5
  class Response
6
- attr_accessor :response, :document, :logger, :settings, :namespace
6
+ ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
7
+ PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
8
+
9
+ attr_accessor :response, :document, :logger, :settings
7
10
 
8
11
  def initialize(response)
9
12
  raise ArgumentError.new("Response cannot be nil") if response.nil?
10
- self.response = response
11
- self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
12
- self.namespace = "saml"
13
-
14
- if document.elements["/#{namespace}p:Response/"].nil?
15
- self.namespace = "saml2"
16
- end
13
+ self.response = response
14
+ self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
17
15
  end
18
16
 
19
17
  def is_valid?
@@ -26,36 +24,40 @@ module Onelogin::Saml
26
24
 
27
25
  # The value of the user identifier as designated by the initialization request response
28
26
  def name_id
29
- @name_id ||= document.elements["/#{namespace}p:Response/#{namespace}:Assertion/#{namespace}:Subject/#{namespace}:NameID"].text
27
+ @name_id ||= begin
28
+ node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
29
+ node.text
30
+ end
30
31
  end
31
32
 
32
- # A hash of alle the attributes with the response. Assuming there is onlye one value for each key
33
+ # A hash of alle the attributes with the response. Assuming there is only one value for each key
33
34
  def attributes
34
- saml_attribute_statements = document.elements["/#{namespace}p:Response/#{namespace}:Assertion/#{namespace}:AttributeStatement"].elements
35
- statements = saml_attribute_statements.map do |child|
36
- child.attributes.map do |key, attribute|
37
- [attribute, child.elements.first.text]
35
+ @attr_statements ||= begin
36
+ result = {}
37
+
38
+ stmt_element = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AttributeStatement", { "p" => PROTOCOL, "a" => ASSERTION })
39
+ stmt_element.elements.each do |attr_element|
40
+ name = attr_element.attributes["Name"]
41
+ value = attr_element.elements.first.text
42
+
43
+ result[name] = value
38
44
  end
39
- end
40
45
 
41
- hash = Hash[statements.flatten(1)]
42
- @attributes ||= make_hash_access_indiferent(hash)
46
+ result.keys.each do |key|
47
+ result[key.intern] = result[key]
48
+ end
49
+
50
+ result
51
+ end
43
52
  end
44
53
 
45
54
  # When this user session should expire at latest
46
55
  def session_expires_at
47
- @expires_at ||= Time.parse(document.elements["/#{namespace}p:Response/#{namespace}:Assertion/#{namespace}:AuthnStatement"].attributes["SessionNotOnOrAfter"])
48
- end
49
-
50
- private
51
-
52
- def make_hash_access_indiferent(hash)
53
- sym_hash = {}
54
- hash.each do |key, value|
55
- sym_hash[key.intern] = value
56
+ @expires_at ||= begin
57
+ node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AuthnStatement", { "p" => PROTOCOL, "a" => ASSERTION })
58
+ Time.parse(node.attributes["SessionNotOnOrAfter"]) if node && node.attributes["SessionNotOnOrAfter"]
56
59
  end
57
-
58
- sym_hash.merge(hash)
59
60
  end
61
+
60
62
  end
61
63
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruby-saml}
8
- s.version = "0.3.4"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["OneLogin LLC"]
12
- s.date = %q{2011-04-28}
12
+ s.date = %q{2011-05-03}
13
13
  s.description = %q{SAML toolkit for Ruby on Rails}
14
14
  s.email = %q{support@onelogin.com}
15
15
  s.extra_rdoc_files = [
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  "ruby-saml.gemspec",
33
33
  "test/responses/response1.xml.base64",
34
34
  "test/responses/response2.xml.base64",
35
+ "test/responses/response3.xml.base64",
35
36
  "test/ruby-saml_test.rb",
36
37
  "test/test_helper.rb",
37
38
  "test/xml_security_test.rb"
@@ -0,0 +1,66 @@
1
+ PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzYW1scDpSZXNwb25zZSB4bWxuczpz
2
+ YW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIiBJ
3
+ RD0iXzZiODVkMGRkLWJmYTgtNGRlZi04MmMyLTg2MjFlMDQ1MjQ3NyIgVmVy
4
+ c2lvbj0iMi4wIiBJc3N1ZUluc3RhbnQ9IjIwMTEtMDUtMDJUMTk6NDM6NTQu
5
+ NjkyWiIgRGVzdGluYXRpb249Imh0dHBzOi8vZXhhbXBsZS5jb20vYWNjZXNz
6
+ L3NhbWwiIENvbnNlbnQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpj
7
+ b25zZW50OnVuc3BlY2lmaWVkIiBJblJlc3BvbnNlVG89Il9mYjg0MThkMC01
8
+ NzFlLTAxMmUtZWVlMC0wMDUwNTY5MjAwZDAiPgogIDxJc3N1ZXIgeG1sbnM9
9
+ InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHA6
10
+ Ly9leGFtcGxlLmNvbS9zZXJ2aWNlcy90cnVzdDwvSXNzdWVyPgogIDxzYW1s
11
+ cDpTdGF0dXM+CiAgICA8c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9h
12
+ c2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+CiAgPC9z
13
+ YW1scDpTdGF0dXM+CiAgPEFzc2VydGlvbiB4bWxucz0idXJuOm9hc2lzOm5h
14
+ bWVzOnRjOlNBTUw6Mi4wOmFzc2VydGlvbiIgSUQ9Il9kYmU2YTM2NS05NTgy
15
+ LTQ2MGYtYjRiMS0xZjc5YmY3MGY3NmIiIElzc3VlSW5zdGFudD0iMjAxMS0w
16
+ NS0wMlQxOTo0Mzo1NC42NDVaIiBWZXJzaW9uPSIyLjAiPgogICAgPElzc3Vl
17
+ cj5odHRwOi8vZXhhbXBsZS5jb20vc2VydmljZXMvdHJ1c3Q8L0lzc3Vlcj4K
18
+ ICAgIDxkczpTaWduYXR1cmUgeG1sbnM6ZHM9Imh0dHA6Ly93d3cudzMub3Jn
19
+ LzIwMDAvMDkveG1sZHNpZyMiPgogICAgICA8ZHM6U2lnbmVkSW5mbz4KICAg
20
+ ICAgICA8ZHM6Q2Fub25pY2FsaXphdGlvbk1ldGhvZCBBbGdvcml0aG09Imh0
21
+ dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPgogICAg
22
+ ICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3
23
+ LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjcnNhLXNoYTEiLz4KICAgICAgICA8
24
+ ZHM6UmVmZXJlbmNlIFVSST0iI19kYmU2YTM2NS05NTgyLTQ2MGYtYjRiMS0x
25
+ Zjc5YmY3MGY3NmIiPgogICAgICAgICAgPGRzOlRyYW5zZm9ybXM+CiAgICAg
26
+ ICAgICAgIDxkczpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3Lncz
27
+ Lm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPgog
28
+ ICAgICAgICAgICA8ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3
29
+ dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+CiAgICAgICAgICA8
30
+ L2RzOlRyYW5zZm9ybXM+CiAgICAgICAgICA8ZHM6RGlnZXN0TWV0aG9kIEFs
31
+ Z29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI3No
32
+ YTEiLz4KICAgICAgICAgIDxkczpEaWdlc3RWYWx1ZT5EaWdlc3Q8L2RzOkRp
33
+ Z2VzdFZhbHVlPgogICAgICAgIDwvZHM6UmVmZXJlbmNlPgogICAgICA8L2Rz
34
+ OlNpZ25lZEluZm8+CiAgICAgIDxkczpTaWduYXR1cmVWYWx1ZT5TaWduYXR1
35
+ cmU8L2RzOlNpZ25hdHVyZVZhbHVlPgogICAgICA8S2V5SW5mbyB4bWxucz0i
36
+ aHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+CiAgICAgICAg
37
+ PGRzOlg1MDlEYXRhPgogICAgICAgICAgPGRzOlg1MDlDZXJ0aWZpY2F0ZT5T
38
+ dHVmZjwvZHM6WDUwOUNlcnRpZmljYXRlPgogICAgICAgIDwvZHM6WDUwOURh
39
+ dGE+CiAgICAgIDwvS2V5SW5mbz4KICAgIDwvZHM6U2lnbmF0dXJlPgogICAg
40
+ PFN1YmplY3Q+CiAgICAgIDxOYW1lSUQgRm9ybWF0PSJ1cm46b2FzaXM6bmFt
41
+ ZXM6dGM6U0FNTDoxLjE6bmFtZWlkLWZvcm1hdDplbWFpbEFkZHJlc3MiPnNv
42
+ bWVvbmVAZXhhbXBsZS5jb208L05hbWVJRD4KICAgICAgPFN1YmplY3RDb25m
43
+ aXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6
44
+ Y206YmVhcmVyIj4KICAgICAgICA8U3ViamVjdENvbmZpcm1hdGlvbkRhdGEg
45
+ SW5SZXNwb25zZVRvPSJfZmI4NDE4ZDAtNTcxZS0wMTJlLWVlZTAtMDA1MDU2
46
+ OTIwMGQwIiBOb3RPbk9yQWZ0ZXI9IjIwMTEtMDUtMDJUMTk6NDg6NTQuNzA3
47
+ WiIgUmVjaXBpZW50PSJodHRwczovL2V4YW1wbGUuY29tL2FjY2Vzcy9zYW1s
48
+ Ii8+CiAgICAgIDwvU3ViamVjdENvbmZpcm1hdGlvbj4KICAgIDwvU3ViamVj
49
+ dD4KICAgIDxDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAxMS0wNS0wMlQxOTo0
50
+ Mzo1NC42NDVaIiBOb3RPbk9yQWZ0ZXI9IjIwMTEtMDUtMDJUMjA6NDM6NTQu
51
+ NjQ1WiI+CiAgICAgIDxBdWRpZW5jZVJlc3RyaWN0aW9uPgogICAgICAgIDxB
52
+ dWRpZW5jZT5jb25zdW1lci5leGFtcGxlLmNvbTwvQXVkaWVuY2U+CiAgICAg
53
+ IDwvQXVkaWVuY2VSZXN0cmljdGlvbj4KICAgIDwvQ29uZGl0aW9ucz4KICAg
54
+ IDxBdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICAgIDxBdHRyaWJ1dGUgTmFtZT0i
55
+ aHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0
56
+ eS9jbGFpbXMvZW1haWxhZGRyZXNzIj4KICAgICAgICA8QXR0cmlidXRlVmFs
57
+ dWU+c29tZW9uZUBleGFtcGxlLmNvbTwvQXR0cmlidXRlVmFsdWU+CiAgICAg
58
+ IDwvQXR0cmlidXRlPgogICAgPC9BdHRyaWJ1dGVTdGF0ZW1lbnQ+CiAgICA8
59
+ QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDExLTA1LTAyVDE5OjQz
60
+ OjU0LjI4NVoiIFNlc3Npb25JbmRleD0iX2RiZTZhMzY1LTk1ODItNDYwZi1i
61
+ NGIxLTFmNzliZjcwZjc2YiI+CiAgICAgIDxBdXRobkNvbnRleHQ+CiAgICAg
62
+ ICAgPEF1dGhuQ29udGV4dENsYXNzUmVmPnVybjpvYXNpczpuYW1lczp0YzpT
63
+ QU1MOjIuMDphYzpjbGFzc2VzOlBhc3N3b3JkUHJvdGVjdGVkVHJhbnNwb3J0
64
+ PC9BdXRobkNvbnRleHRDbGFzc1JlZj4KICAgICAgPC9BdXRobkNvbnRleHQ+
65
+ CiAgICA8L0F1dGhuU3RhdGVtZW50PgogIDwvQXNzZXJ0aW9uPgo8L3NhbWxw
66
+ OlJlc3BvbnNlPgo=
@@ -35,6 +35,8 @@ class RubySamlTest < Test::Unit::TestCase
35
35
  assert !response.name_id.nil?
36
36
  response = Onelogin::Saml::Response.new(response_document_2)
37
37
  assert !response.name_id.nil?
38
+ response = Onelogin::Saml::Response.new(response_document_3)
39
+ assert !response.name_id.nil?
38
40
  end
39
41
 
40
42
  context "#is_valid?" do
@@ -65,6 +67,9 @@ class RubySamlTest < Test::Unit::TestCase
65
67
  should "extract the value of the name id element" do
66
68
  response = Onelogin::Saml::Response.new(response_document)
67
69
  assert_equal "support@onelogin.com", response.name_id
70
+
71
+ response = Onelogin::Saml::Response.new(response_document_3)
72
+ assert_equal "someone@example.com", response.name_id
68
73
  end
69
74
  end
70
75
 
@@ -84,12 +89,20 @@ class RubySamlTest < Test::Unit::TestCase
84
89
  assert_equal "demo", response.attributes[:uid]
85
90
  assert_equal "value", response.attributes[:another_value]
86
91
  end
92
+
93
+ should "work for implicit namespaces" do
94
+ response = Onelogin::Saml::Response.new(response_document_3)
95
+ assert_equal "someone@example.com", response.attributes["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
96
+ end
87
97
  end
88
98
 
89
99
  context "#session_expires_at" do
90
100
  should "extract the value of the SessionNotOnOrAfter attribute" do
91
101
  response = Onelogin::Saml::Response.new(response_document)
92
102
  assert response.session_expires_at.is_a?(Time)
103
+
104
+ response = Onelogin::Saml::Response.new(response_document_2)
105
+ assert response.session_expires_at.nil?
93
106
  end
94
107
  end
95
108
  end
@@ -15,4 +15,9 @@ class Test::Unit::TestCase
15
15
  def response_document_2
16
16
  @response_document2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response2.xml.base64'))
17
17
  end
18
+
19
+ def response_document_3
20
+ @response_document3 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response3.xml.base64'))
21
+ end
22
+
18
23
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
9
8
  - 4
10
- version: 0.3.4
9
+ - 0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - OneLogin LLC
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-28 00:00:00 +02:00
18
+ date: 2011-05-03 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -101,6 +101,7 @@ files:
101
101
  - ruby-saml.gemspec
102
102
  - test/responses/response1.xml.base64
103
103
  - test/responses/response2.xml.base64
104
+ - test/responses/response3.xml.base64
104
105
  - test/ruby-saml_test.rb
105
106
  - test/test_helper.rb
106
107
  - test/xml_security_test.rb