simple_oauth 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Steve Richert
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = simple_oauth
2
+
3
+ Simply builds and verifies OAuth headers
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Steve Richert. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require './lib/simple_oauth'
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.name = 'simple_oauth'
11
+ gem.version = SimpleOAuth::Version::STRING
12
+ gem.summary = 'Simply builds and verifies OAuth headers'
13
+ gem.description = 'Simply builds and verifies OAuth headers'
14
+ gem.email = 'steve.richert@gmail.com'
15
+ gem.homepage = 'http://github.com/laserlemon/simple_oauth'
16
+ gem.authors = ['Steve Richert']
17
+ gem.add_development_dependency 'mocha'
18
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
19
+ end
20
+ Jeweler::GemcutterTasks.new
21
+ rescue LoadError
22
+ puts 'Jeweler is not available. Install it with: gem install jeweler'
23
+ end
24
+
25
+ Rake::TestTask.new do |test|
26
+ test.libs << 'lib' << 'test'
27
+ test.pattern = 'test/**/*_test.rb'
28
+ test.verbose = true
29
+ end
30
+
31
+ task :test => :check_dependencies
32
+
33
+ task :default => :test
34
+
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |rcov|
38
+ rcov.libs << 'lib' << 'test'
39
+ rcov.pattern = 'test/**/*_test.rb'
40
+ rcov.verbose = true
41
+ rcov.rcov_opts << '--exclude "gems/*"'
42
+ end
43
+ rescue LoadError
44
+ task :rcov do
45
+ abort 'RCov is not available. Install it with: gem install rcov'
46
+ end
47
+ end
48
+
49
+ Rake::RDocTask.new do |rdoc|
50
+ version = SimpleOAuth::Version::STRING
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "simple_oauth #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path('../lib/simple_oauth', __FILE__)
@@ -0,0 +1,117 @@
1
+ require 'base64'
2
+ require 'cgi'
3
+ require 'openssl'
4
+ require 'uri'
5
+
6
+ module SimpleOAuth
7
+ module Version
8
+ MAJOR = 0
9
+ MINOR = 1
10
+ PATCH = 0
11
+ STRING = [MAJOR, MINOR, PATCH].join('.')
12
+ end
13
+
14
+ class Header
15
+ ATTRIBUTE_KEYS = [:consumer_key, :nonce, :signature_method, :timestamp, :token, :version]
16
+
17
+ def self.default_options
18
+ {
19
+ :nonce => OpenSSL::Random.random_bytes(16).unpack('H*')[0],
20
+ :signature_method => 'HMAC-SHA1',
21
+ :timestamp => Time.now.to_i.to_s,
22
+ :version => '1.0'
23
+ }
24
+ end
25
+
26
+ def self.encode(value)
27
+ URI.encode(value.to_s, /[^\w\-\.\~]/)
28
+ end
29
+
30
+ def self.decode(value)
31
+ URI.decode(value.to_s)
32
+ end
33
+
34
+ def self.parse(header)
35
+ header.to_s.sub(/^OAuth\s/, '').split(', ').inject({}) do |attributes, pair|
36
+ match = pair.match(/^(\w+)\=\"([^\"]*)\"$/)
37
+ attributes.merge(match[1].sub(/^oauth_/, '').to_sym => decode(match[2]))
38
+ end
39
+ end
40
+
41
+ attr_reader :method, :params, :options
42
+
43
+ def initialize(method, url, params, oauth = {})
44
+ @method = method.to_s.upcase
45
+ @uri = URI.parse(url).tap do |uri|
46
+ uri.scheme = uri.scheme.downcase
47
+ uri.normalize!
48
+ uri.fragment = nil
49
+ end
50
+ @params = params
51
+ @options = oauth.is_a?(Hash) ? self.class.default_options.merge(oauth) : self.class.parse(oauth)
52
+ end
53
+
54
+ def url
55
+ @uri.dup.tap{|u| u.query = nil }.to_s
56
+ end
57
+
58
+ def to_s
59
+ "OAuth #{normalized_attributes}"
60
+ end
61
+
62
+ def valid?(secrets = {})
63
+ original_options = options.dup
64
+ options.merge!(secrets)
65
+ valid = options[:signature] == signature
66
+ options.replace(original_options)
67
+ valid
68
+ end
69
+
70
+ private
71
+ def normalized_attributes
72
+ signed_attributes.sort_by(&:to_s).map{|k,v| %(#{k}="#{self.class.encode(v)}") }.join(', ')
73
+ end
74
+
75
+ def signed_attributes
76
+ attributes.merge(:oauth_signature => signature)
77
+ end
78
+
79
+ def attributes
80
+ ATTRIBUTE_KEYS.inject({}){|a,k| options.key?(k) ? a.merge(:"oauth_#{k}" => options[k]) : a }
81
+ end
82
+
83
+ def signature
84
+ send(options[:signature_method].downcase.tr('-', '_') + '_signature')
85
+ end
86
+
87
+ def hmac_sha1_signature
88
+ Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), secret, signature_base)).chomp
89
+ end
90
+
91
+ def rsa_sha1_signature
92
+ Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), options[:private_key].to_s, signature_base)).chomp
93
+ end
94
+
95
+ def secret
96
+ options.values_at(:consumer_secret, :token_secret).map{|v| self.class.encode(v) }.join('&')
97
+ end
98
+
99
+ alias_method :plaintext_signature, :secret
100
+
101
+ def signature_base
102
+ [method, url, normalized_params].map{|v| self.class.encode(v) }.join('&')
103
+ end
104
+
105
+ def normalized_params
106
+ signature_params.sort_by(&:to_s).map{|p| p.map{|v| self.class.encode(v) }.join('=') }.join('&')
107
+ end
108
+
109
+ def signature_params
110
+ attributes.to_a + params.to_a + url_params
111
+ end
112
+
113
+ def url_params
114
+ CGI.parse(@uri.query || '').inject([]){|p,(k,vs)| p + vs.map{|v| [k, v] } }
115
+ end
116
+ end
117
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+ require 'simple_oauth'
3
+ require 'rubygems'
4
+ require 'mocha'
@@ -0,0 +1,260 @@
1
+ require 'helper'
2
+
3
+ class SimpleOAuthTest < Test::Unit::TestCase
4
+ def test_initialize
5
+ header = SimpleOAuth::Header.new(:get, 'HTTPS://api.TWITTER.com:443/1/statuses/friendships.json#anchor', {})
6
+
7
+ # HTTP method should be an uppercase string.
8
+ #
9
+ # See: http://oauth.net/core/1.0/#rfc.section.9.1.3
10
+ assert_equal 'GET', header.method
11
+
12
+ # Request URL should downcase the scheme and authority parts as well as
13
+ # remove the query and fragment parts.
14
+ #
15
+ # See: http://oauth.net/core/1.0/#rfc.section.9.1.2
16
+ assert_equal 'https://api.twitter.com/1/statuses/friendships.json', header.url
17
+ end
18
+
19
+ def test_default_options
20
+ # Default header options should change with each call due to generation of
21
+ # a unique "timestamp" and "nonce" value combination.
22
+ default_options = SimpleOAuth::Header.default_options
23
+ assert_not_equal default_options, SimpleOAuth::Header.default_options
24
+
25
+ SimpleOAuth::Header.stubs(:default_options).returns(default_options)
26
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {})
27
+
28
+ # Given no options argument, header options defer to the default options.
29
+ assert_equal default_options, header.options
30
+
31
+ # Default options should include a signature method and the OAuth version.
32
+ assert_equal 'HMAC-SHA1', default_options[:signature_method]
33
+ assert_equal '1.0', default_options[:version]
34
+ end
35
+
36
+ def test_attributes
37
+ attribute_options = SimpleOAuth::Header::ATTRIBUTE_KEYS.inject({}){|o,a| o.merge(a => a.to_s.upcase) }
38
+ options = attribute_options.merge(:other => 'OTHER')
39
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {}, options)
40
+ attributes = header.send(:attributes)
41
+
42
+ # OAuth header attributes are all to begin with the "oauth_" prefix.
43
+ assert attributes.all?{|k,v| k.to_s =~ /^oauth_/ }
44
+
45
+ # Custom options not included in the list of valid attribute keys should
46
+ # not be included in the header attributes.
47
+ assert !attributes.key?(:oauth_other)
48
+
49
+ # Valid attribute option values should be preserved.
50
+ assert_equal attribute_options.size, attributes.size
51
+ assert attributes.all?{|k,v| k.to_s == "oauth_#{v.downcase}" }
52
+ end
53
+
54
+ def test_encode
55
+ # Non-word characters should be URL encoded...
56
+ [' ', '!', '@', '#', '$', '%', '^', '&'].each do |character|
57
+ encoded = SimpleOAuth::Header.encode(character)
58
+ assert_not_equal character, encoded
59
+ assert_equal URI.encode(character, /.*/), encoded
60
+ end
61
+
62
+ # ...except for the "-", "." and "~" characters.
63
+ ['-', '.', '~'].each do |character|
64
+ assert_equal character, SimpleOAuth::Header.encode(character)
65
+ end
66
+ end
67
+
68
+ def test_url_params
69
+ # A URL with no query parameters should produce empty +url_params+
70
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {})
71
+ assert_equal [], header.send(:url_params)
72
+
73
+ # A URL with query parameters should return a hash having array values
74
+ # containing the given query parameters.
75
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json?test=TEST', {})
76
+ url_params = header.send(:url_params)
77
+ assert_kind_of Array, url_params
78
+ assert_equal [['test', 'TEST']], url_params
79
+
80
+ # If a query parameter is repeated, the values should be sorted.
81
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json?test=1&test=2', {})
82
+ assert_equal [['test', '1'], ['test', '2']], header.send(:url_params)
83
+ end
84
+
85
+ def test_signature_params
86
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {})
87
+ header.stubs(:attributes).returns(:attribute => 'ATTRIBUTE')
88
+ header.stubs(:params).returns('param' => 'PARAM')
89
+ header.stubs(:url_params).returns([['url_param', '1'], ['url_param', '2']])
90
+
91
+ # Should combine OAuth header attributes, body parameters and URL
92
+ # parameters into an array of key value pairs.
93
+ signature_params = header.send(:signature_params)
94
+ assert_kind_of Array, signature_params
95
+ assert_equal [:attribute, 'param', 'url_param', 'url_param'], signature_params.map(&:first)
96
+ assert_equal ['ATTRIBUTE', 'PARAM', '1', '2'], signature_params.map(&:last)
97
+ end
98
+
99
+ def test_normalized_params
100
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {})
101
+ header.stubs(:signature_params).returns([['A', '4'], ['B', '3'], ['B', '2'], ['C', '1'], ['D[]', '0 ']])
102
+
103
+ # The +normalized_params+ string should join key=value pairs with
104
+ # ampersands.
105
+ signature_params = header.send(:signature_params)
106
+ normalized_params = header.send(:normalized_params)
107
+ parts = normalized_params.split('&')
108
+ pairs = parts.map{|p| p.split('=') }
109
+ assert_kind_of String, normalized_params
110
+ assert_equal signature_params.size, parts.size
111
+ assert pairs.all?{|p| p.size == 2 }
112
+
113
+ # The signature parameters should be sorted and the keys/values URL encoded
114
+ # first.
115
+ assert_equal signature_params.sort_by(&:to_s), pairs.map{|k,v| [URI.decode(k), URI.decode(v)] }
116
+ end
117
+
118
+ def test_signature_base
119
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {})
120
+ header.stubs(:method).returns('METHOD')
121
+ header.stubs(:url).returns('URL')
122
+ header.stubs(:normalized_params).returns('NORMALIZED_PARAMS')
123
+
124
+ # Should combine HTTP method, URL and normalized parameters string using
125
+ # ampersands.
126
+ assert_equal 'METHOD&URL&NORMALIZED_PARAMS', header.send(:signature_base)
127
+
128
+ header.stubs(:method).returns('ME#HOD')
129
+ header.stubs(:url).returns('U#L')
130
+ header.stubs(:normalized_params).returns('NORMAL#ZED_PARAMS')
131
+
132
+ # Each of the three combined values should be URL encoded.
133
+ assert_equal 'ME%23HOD&U%23L&NORMAL%23ZED_PARAMS', header.send(:signature_base)
134
+ end
135
+
136
+ def test_secret
137
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friendships.json', {})
138
+ header.stubs(:options).returns(:consumer_secret => 'CONSUMER_SECRET', :token_secret => 'TOKEN_SECRET')
139
+
140
+ # Should combine the consumer and token secrets with an ampersand.
141
+ assert_equal 'CONSUMER_SECRET&TOKEN_SECRET', header.send(:secret)
142
+
143
+ header.stubs(:options).returns(:consumer_secret => 'CONSUM#R_SECRET', :token_secret => 'TOKEN_S#CRET')
144
+
145
+ # Should URL encode each secret value before combination.
146
+ assert_equal 'CONSUM%23R_SECRET&TOKEN_S%23CRET', header.send(:secret)
147
+ end
148
+
149
+ def test_hmac_sha1_signature
150
+ # Reproduce an actual successful call to the Twitter API using the
151
+ # HMAC-SHA1 signature method, GETting a list of friends.
152
+ options = {
153
+ :consumer_key => '8karQBlMg6gFOwcf8kcoYw',
154
+ :consumer_secret => '3d0vcHyUiiqADpWxolW8nlDIpSWMlyK7YNgc5Qna2M',
155
+ :nonce => '547fed103e122eecf84c080843eedfe6',
156
+ #:signature_method => 'HMAC-SHA1',
157
+ :timestamp => '1286830180',
158
+ :token => '201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh',
159
+ :token_secret => 'T5qa1tF57tfDzKmpM89DHsNuhgOY4NT6DlNLsTFcuQ'
160
+ }
161
+ successful = 'OAuth oauth_consumer_key="8karQBlMg6gFOwcf8kcoYw", oauth_nonce="547fed103e122eecf84c080843eedfe6", oauth_signature="i9CT6ahDRAlfGX3hKYf78QzXsaw%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1286830180", oauth_token="201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh", oauth_version="1.0"'
162
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, options)
163
+ assert_equal successful, header.to_s
164
+
165
+ # Reproduce a successful Twitter call, POSTing a new status.
166
+ options.merge!(
167
+ :nonce => 'b40a3e0f18590ecdcc0e273f7d7c82f8',
168
+ :timestamp => '1286830181'
169
+ )
170
+ successful = 'OAuth oauth_consumer_key="8karQBlMg6gFOwcf8kcoYw", oauth_nonce="b40a3e0f18590ecdcc0e273f7d7c82f8", oauth_signature="mPqSFKejrWWk3ZT9bTQjhO5b2xI%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1286830181", oauth_token="201425800-Sv4sTcgoffmHGkTCue0JnURT8vrm4DiFAkeFNDkh", oauth_version="1.0"'
171
+ header = SimpleOAuth::Header.new(:post, 'https://api.twitter.com/1/statuses/update.json', {:status => 'hi, again'}, options)
172
+ assert_equal successful, header.to_s
173
+ end
174
+
175
+ def test_signature
176
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => 'HMAC-SHA1')
177
+ header.expects(:hmac_sha1_signature).once.returns('HMAC_SHA1_SIGNATURE')
178
+ assert_equal 'HMAC_SHA1_SIGNATURE', header.send(:signature)
179
+
180
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => 'RSA-SHA1', :private_key => 'PRIVATE_KEY')
181
+ header.expects(:rsa_sha1_signature).once.returns('RSA_SHA1_SIGNATURE')
182
+ assert_equal 'RSA_SHA1_SIGNATURE', header.send(:signature)
183
+
184
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => 'PLAINTEXT')
185
+ header.expects(:plaintext_signature).once.returns('PLAINTEXT_SIGNATURE')
186
+ assert_equal 'PLAINTEXT_SIGNATURE', header.send(:signature)
187
+ end
188
+
189
+ def test_signed_attributes
190
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {})
191
+ assert header.send(:signed_attributes).keys.include?(:oauth_signature)
192
+ end
193
+
194
+ def test_normalized_attributes
195
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {})
196
+ header.stubs(:signed_attributes).returns(:d => 1, :c => 2, :b => 3, :a => 4)
197
+
198
+ # Should return the OAuth header attributes, sorted by name, with quoted
199
+ # values and comma-separated.
200
+ assert_equal 'a="4", b="3", c="2", d="1"', header.send(:normalized_attributes)
201
+
202
+ # Values should also be URL encoded.
203
+ header.stubs(:signed_attributes).returns(1 => '!', 2 => '@', 3 => '#', 4 => '$')
204
+ assert_equal '1="%21", 2="%40", 3="%23", 4="%24"', header.send(:normalized_attributes)
205
+ end
206
+
207
+ def test_to_s
208
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {})
209
+ assert_equal "OAuth #{header.send(:normalized_attributes)}", header.to_s
210
+ end
211
+
212
+ def test_parse
213
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {})
214
+ parsed_options = SimpleOAuth::Header.parse(header)
215
+
216
+ # Parsed options should be a Hash.
217
+ assert_kind_of Hash, parsed_options
218
+
219
+ # Parsed options should equal the options used to build the header, along
220
+ # with the additional signature.
221
+ assert_equal header.options, parsed_options.reject{|k,v| k == :signature }
222
+ end
223
+
224
+ def test_valid
225
+ # With no consumer or token secrets, built headers should be valid when
226
+ # parsed without secrets, regardless of signature method.
227
+ ['HMAC-SHA1', 'RSA-SHA1', 'PLAINTEXT'].each do |signature_method|
228
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, :signature_method => signature_method)
229
+ parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header)
230
+ assert_equal signature_method, parsed_header.options[:signature_method]
231
+ assert parsed_header.valid?
232
+ end
233
+
234
+ # When given consumer and token secrets, those secrets must be passed into
235
+ # the parsed header validation in order for the validity check to pass.
236
+ secrets = {:consumer_secret => 'CONSUMER_SECRET', :token_secret => 'TOKEN_SECRET'}
237
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, secrets)
238
+ parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header)
239
+ assert !parsed_header.valid?
240
+ assert parsed_header.valid?(secrets)
241
+
242
+ # Using the RSA-SHA1 signature method, a private key should be included
243
+ # with the options. When parsing the header on the server side, the
244
+ # the private key must be included in order for the header to validate.
245
+ secrets = {:private_key => 'PRIVATE_KEY'}
246
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, secrets.merge(:signature_method => 'RSA-SHA1'))
247
+ parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header)
248
+ assert !parsed_header.valid?
249
+ assert parsed_header.valid?(secrets)
250
+
251
+ # Like the default HMAC-RSA1 signature method, the PLAINTEXT method
252
+ # requires use of both a consumer secret and a token secret. A parsed
253
+ # header will not validate without these secret values.
254
+ secrets = {:consumer_secret => 'CONSUMER_SECRET', :token_secret => 'TOKEN_SECRET'}
255
+ header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, secrets.merge(:signature_method => 'PLAINTEXT'))
256
+ parsed_header = SimpleOAuth::Header.new(:get, 'https://api.twitter.com/1/statuses/friends.json', {}, header)
257
+ assert !parsed_header.valid?
258
+ assert parsed_header.valid?(secrets)
259
+ end
260
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_oauth
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Steve Richert
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-11 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: mocha
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ description: Simply builds and verifies OAuth headers
34
+ email: steve.richert@gmail.com
35
+ executables: []
36
+
37
+ extensions: []
38
+
39
+ extra_rdoc_files:
40
+ - LICENSE
41
+ - README.rdoc
42
+ files:
43
+ - .gitignore
44
+ - LICENSE
45
+ - README.rdoc
46
+ - Rakefile
47
+ - init.rb
48
+ - lib/simple_oauth.rb
49
+ - test/helper.rb
50
+ - test/simple_oauth_test.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/laserlemon/simple_oauth
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Simply builds and verifies OAuth headers
83
+ test_files:
84
+ - test/helper.rb
85
+ - test/simple_oauth_test.rb