ruby-saml 0.4.7 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

@@ -38,6 +38,10 @@ class Test::Unit::TestCase
38
38
  @response_document5 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response5.xml.base64'))
39
39
  end
40
40
 
41
+ def ampersands_response
42
+ @ampersands_resposne ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_with_ampersands.xml.base64'))
43
+ end
44
+
41
45
  def response_document_6
42
46
  doc = Base64.decode64(response_document)
43
47
  doc.gsub!(/NotBefore=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotBefore=\"#{(Time.now-300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
@@ -45,6 +49,10 @@ class Test::Unit::TestCase
45
49
  Base64.encode64(doc)
46
50
  end
47
51
 
52
+ def wrapped_response_2
53
+ @wrapped_response_2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'wrapped_response_2.xml.base64'))
54
+ end
55
+
48
56
  def signature_fingerprint_1
49
57
  @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
50
58
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 4
9
- - 7
10
- version: 0.4.7
7
+ - 5
8
+ - 0
9
+ version: 0.5.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - OneLogin LLC
@@ -15,18 +14,16 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-06-30 00:00:00 +02:00
17
+ date: 2011-06-30 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: canonix
23
22
  prerelease: false
24
23
  requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
25
  - - ~>
28
26
  - !ruby/object:Gem::Version
29
- hash: 9
30
27
  segments:
31
28
  - 0
32
29
  - 1
@@ -37,11 +34,9 @@ dependencies:
37
34
  name: uuid
38
35
  prerelease: false
39
36
  requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
37
  requirements:
42
38
  - - ~>
43
39
  - !ruby/object:Gem::Version
44
- hash: 5
45
40
  segments:
46
41
  - 2
47
42
  - 3
@@ -52,11 +47,9 @@ dependencies:
52
47
  name: shoulda
53
48
  prerelease: false
54
49
  requirement: &id003 !ruby/object:Gem::Requirement
55
- none: false
56
50
  requirements:
57
51
  - - ">="
58
52
  - !ruby/object:Gem::Version
59
- hash: 3
60
53
  segments:
61
54
  - 0
62
55
  version: "0"
@@ -66,11 +59,9 @@ dependencies:
66
59
  name: ruby-debug
67
60
  prerelease: false
68
61
  requirement: &id004 !ruby/object:Gem::Requirement
69
- none: false
70
62
  requirements:
71
63
  - - ">="
72
64
  - !ruby/object:Gem::Version
73
- hash: 3
74
65
  segments:
75
66
  - 0
76
67
  version: "0"
@@ -80,11 +71,9 @@ dependencies:
80
71
  name: mocha
81
72
  prerelease: false
82
73
  requirement: &id005 !ruby/object:Gem::Requirement
83
- none: false
84
74
  requirements:
85
75
  - - ">="
86
76
  - !ruby/object:Gem::Version
87
- hash: 3
88
77
  segments:
89
78
  - 0
90
79
  version: "0"
@@ -106,11 +95,13 @@ files:
106
95
  - README.rdoc
107
96
  - Rakefile
108
97
  - VERSION
109
- - lib/onelogin/saml.rb
110
- - lib/onelogin/saml/authrequest.rb
111
- - lib/onelogin/saml/response.rb
112
- - lib/onelogin/saml/settings.rb
113
- - lib/onelogin/saml/validation_error.rb
98
+ - lib/onelogin/ruby-saml/authrequest.rb
99
+ - lib/onelogin/ruby-saml/logging.rb
100
+ - lib/onelogin/ruby-saml/metadata.rb
101
+ - lib/onelogin/ruby-saml/response.rb
102
+ - lib/onelogin/ruby-saml/settings.rb
103
+ - lib/onelogin/ruby-saml/validation_error.rb
104
+ - lib/onelogin/ruby-saml/version.rb
114
105
  - lib/ruby-saml.rb
115
106
  - lib/xml_security.rb
116
107
  - ruby-saml.gemspec
@@ -124,7 +115,10 @@ files:
124
115
  - test/responses/response3.xml.base64
125
116
  - test/responses/response4.xml.base64
126
117
  - test/responses/response5.xml.base64
118
+ - test/responses/response_with_ampersands.xml
119
+ - test/responses/response_with_ampersands.xml.base64
127
120
  - test/responses/simple_saml_php.xml
121
+ - test/responses/wrapped_response_2.xml.base64
128
122
  - test/settings_test.rb
129
123
  - test/test_helper.rb
130
124
  - test/xml_security_test.rb
@@ -138,33 +132,41 @@ rdoc_options:
138
132
  require_paths:
139
133
  - lib
140
134
  required_ruby_version: !ruby/object:Gem::Requirement
141
- none: false
142
135
  requirements:
143
136
  - - ">="
144
137
  - !ruby/object:Gem::Version
145
- hash: 3
146
138
  segments:
147
139
  - 0
148
140
  version: "0"
149
141
  required_rubygems_version: !ruby/object:Gem::Requirement
150
- none: false
151
142
  requirements:
152
143
  - - ">="
153
144
  - !ruby/object:Gem::Version
154
- hash: 3
155
145
  segments:
156
146
  - 0
157
147
  version: "0"
158
148
  requirements: []
159
149
 
160
- rubyforge_project:
161
- rubygems_version: 1.3.7
150
+ rubyforge_project: http://www.rubygems.org/gems/ruby-saml
151
+ rubygems_version: 1.3.6
162
152
  signing_key:
163
153
  specification_version: 3
164
154
  summary: SAML Ruby Tookit
165
155
  test_files:
156
+ - test/certificates/certificate1
166
157
  - test/request_test.rb
167
158
  - test/response_test.rb
159
+ - test/responses/adfs_response.xml.base64
160
+ - test/responses/open_saml_response.xml
161
+ - test/responses/response1.xml.base64
162
+ - test/responses/response2.xml.base64
163
+ - test/responses/response3.xml.base64
164
+ - test/responses/response4.xml.base64
165
+ - test/responses/response5.xml.base64
166
+ - test/responses/response_with_ampersands.xml
167
+ - test/responses/response_with_ampersands.xml.base64
168
+ - test/responses/simple_saml_php.xml
169
+ - test/responses/wrapped_response_2.xml.base64
168
170
  - test/settings_test.rb
169
171
  - test/test_helper.rb
170
172
  - test/xml_security_test.rb
@@ -1,5 +0,0 @@
1
- require 'onelogin/saml/authrequest'
2
- require 'onelogin/saml/response'
3
- require 'onelogin/saml/settings'
4
- require 'onelogin/saml/validation_error'
5
-
@@ -1,33 +0,0 @@
1
- require "base64"
2
- require "uuid"
3
- require "zlib"
4
- require "cgi"
5
-
6
- module Onelogin::Saml
7
- class Authrequest
8
- def create(settings, params = {})
9
- uuid = "_" + UUID.new.generate
10
- time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
11
-
12
- request =
13
- "<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{uuid}\" Version=\"2.0\" IssueInstant=\"#{time}\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"#{settings.assertion_consumer_service_url}\">" +
14
- "<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{settings.issuer}</saml:Issuer>\n" +
15
- "<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"#{settings.name_identifier_format}\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n" +
16
- "<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\">" +
17
- "<saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n" +
18
- "</samlp:AuthnRequest>"
19
-
20
- deflated_request = Zlib::Deflate.deflate(request, 9)[2..-5]
21
- base64_request = Base64.encode64(deflated_request)
22
- encoded_request = CGI.escape(base64_request)
23
- request_params = "?SAMLRequest=" + encoded_request
24
-
25
- params.each_pair do |key, value|
26
- request_params << "&#{key}=#{CGI.escape(value.to_s)}"
27
- end
28
-
29
- settings.idp_sso_target_url + request_params
30
- end
31
-
32
- end
33
- end
@@ -1,137 +0,0 @@
1
- require "xml_security"
2
- require "time"
3
-
4
- module Onelogin::Saml
5
-
6
- class Response
7
- ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
8
- PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
9
- DSIG = "http://www.w3.org/2000/09/xmldsig#"
10
-
11
- attr_accessor :options, :response, :document, :settings
12
-
13
- def initialize(response, options = {})
14
- raise ArgumentError.new("Response cannot be nil") if response.nil?
15
- self.options = options
16
- self.response = response
17
- self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
18
- end
19
-
20
- def is_valid?
21
- validate(soft = true)
22
- end
23
-
24
- def validate!
25
- validate(soft = false)
26
- end
27
-
28
- # The value of the user identifier as designated by the initialization request response
29
- def name_id
30
- @name_id ||= begin
31
- node = REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
32
- node ||= REXML::XPath.first(document, "/p:Response[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
33
- node.nil? ? nil : node.text
34
- end
35
- end
36
-
37
- # A hash of alle the attributes with the response. Assuming there is only one value for each key
38
- def attributes
39
- @attr_statements ||= begin
40
- result = {}
41
-
42
- stmt_element = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AttributeStatement", { "p" => PROTOCOL, "a" => ASSERTION })
43
- return {} if stmt_element.nil?
44
-
45
- stmt_element.elements.each do |attr_element|
46
- name = attr_element.attributes["Name"]
47
- value = attr_element.elements.first.text
48
-
49
- result[name] = value
50
- end
51
-
52
- result.keys.each do |key|
53
- result[key.intern] = result[key]
54
- end
55
-
56
- result
57
- end
58
- end
59
-
60
- # When this user session should expire at latest
61
- def session_expires_at
62
- @expires_at ||= begin
63
- node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AuthnStatement", { "p" => PROTOCOL, "a" => ASSERTION })
64
- parse_time(node, "SessionNotOnOrAfter")
65
- end
66
- end
67
-
68
- # Conditions (if any) for the assertion to run
69
- def conditions
70
- @conditions ||= begin
71
- REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Conditions", { "p" => PROTOCOL, "a" => ASSERTION })
72
- end
73
- end
74
-
75
- private
76
-
77
- def validation_error(message)
78
- raise ValidationError.new(message)
79
- end
80
-
81
- def validate(soft = true)
82
- validate_response_state(soft) &&
83
- validate_conditions(soft) &&
84
- document.validate(get_fingerprint, soft)
85
- end
86
-
87
- def validate_response_state(soft = true)
88
- if response.empty?
89
- return soft ? false : validation_error("Blank response")
90
- end
91
-
92
- if settings.nil?
93
- return soft ? false : validation_error("No settings on response")
94
- end
95
-
96
- if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
97
- return soft ? false : validation_error("No fingerprint or certificate on settings")
98
- end
99
-
100
- true
101
- end
102
-
103
- def get_fingerprint
104
- if settings.idp_cert
105
- cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
106
- Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
107
- else
108
- settings.idp_cert_fingerprint
109
- end
110
- end
111
-
112
- def validate_conditions(soft = true)
113
- return true if conditions.nil?
114
- return true if options[:skip_conditions]
115
-
116
- if not_before = parse_time(conditions, "NotBefore")
117
- if Time.now.utc < not_before
118
- return soft ? false : validation_error("Current time is earlier than NotBefore condition")
119
- end
120
- end
121
-
122
- if not_on_or_after = parse_time(conditions, "NotOnOrAfter")
123
- if Time.now.utc >= not_on_or_after
124
- return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
125
- end
126
- end
127
-
128
- true
129
- end
130
-
131
- def parse_time(node, attribute)
132
- if node && node.attributes[attribute]
133
- Time.parse(node.attributes[attribute])
134
- end
135
- end
136
- end
137
- end
@@ -1,6 +0,0 @@
1
- module Onelogin::Saml
2
- class Settings
3
- attr_accessor :assertion_consumer_service_url, :issuer, :sp_name_qualifier
4
- attr_accessor :idp_sso_target_url, :idp_cert_fingerprint, :idp_cert, :name_identifier_format
5
- end
6
- end