oauth 0.2.7 → 0.3.0

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

Potentially problematic release.


This version of oauth might be problematic. Click here for more details.

Files changed (43) hide show
  1. data/History.txt +14 -0
  2. data/Manifest.txt +19 -3
  3. data/{README.txt → README.rdoc} +0 -0
  4. data/Rakefile +34 -4
  5. data/TODO +14 -0
  6. data/bin/oauth +5 -0
  7. data/lib/oauth.rb +3 -3
  8. data/lib/oauth/cli.rb +130 -0
  9. data/lib/oauth/client/helper.rb +3 -2
  10. data/lib/oauth/consumer.rb +1 -1
  11. data/lib/oauth/helper.rb +3 -0
  12. data/lib/oauth/oauth_test_helper.rb +26 -0
  13. data/lib/oauth/request_proxy/action_controller_request.rb +2 -4
  14. data/lib/oauth/request_proxy/base.rb +31 -0
  15. data/lib/oauth/request_proxy/jabber_request.rb +42 -0
  16. data/lib/oauth/request_proxy/mock_request.rb +36 -0
  17. data/lib/oauth/request_proxy/net_http.rb +0 -2
  18. data/lib/oauth/request_proxy/rack_request.rb +1 -3
  19. data/lib/oauth/signature/base.rb +20 -7
  20. data/lib/oauth/signature/plaintext.rb +1 -1
  21. data/lib/oauth/token.rb +3 -3
  22. data/lib/oauth/version.rb +2 -8
  23. data/oauth.gemspec +43 -0
  24. data/script/txt2html +1 -1
  25. data/specs.txt +13 -0
  26. data/test/cases/oauth_case.rb +19 -0
  27. data/test/cases/spec/1_0-final/test_construct_request_url.rb +62 -0
  28. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +88 -0
  29. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +86 -0
  30. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +77 -0
  31. data/test/keys/rsa.cert +11 -0
  32. data/test/keys/rsa.pem +16 -0
  33. data/test/test_action_controller_request_proxy.rb +2 -1
  34. data/test/test_consumer.rb +17 -18
  35. data/test/test_helper.rb +8 -0
  36. data/test/test_net_http_client.rb +7 -7
  37. data/test/test_net_http_request_proxy.rb +3 -3
  38. data/test/test_rack_request_proxy.rb +3 -3
  39. data/test/test_signature_plain_text.rb +31 -0
  40. data/website/index.html +1 -1
  41. metadata +43 -11
  42. data/config/hoe.rb +0 -71
  43. data/config/requirements.rb +0 -17
@@ -1,3 +1,17 @@
1
+ Fix in plain text signatures to bug found by Andrew Arrow. Who contributed new new unit tests for plain text sigs.
2
+
3
+ == 0.3.0
4
+
5
+ * Support ActionController::Request from Edge Rails (László Bácsi)
6
+ * Correctly handle multi-valued parameters (Seth)
7
+ * Added #normalized_parameters to OAuth::RequestProxy::Base (Pelle)
8
+ * OAuth::Signature.sign and friends now yield the RequestProxy instead of the
9
+ token when the passed block's arity is 1. (Seth)
10
+ * Token requests are made to the configured URL rather than generating a
11
+ potentially incorrect one. (Kellan Elliott-McCrea)
12
+ * Command-line app for generating signatures. (Seth)
13
+ * Improved test-cases and compatibility for encoding issues. (Pelle)
14
+
1
15
  == 0.2.7 2008-9-10 The lets fix the last release release
2
16
 
3
17
  There was an error in the RSA requests using oauth tokens. Thanks to Philip Lipu Tsai for noticing this.
@@ -1,20 +1,24 @@
1
1
  History.txt
2
2
  License.txt
3
3
  Manifest.txt
4
- README.txt
4
+ README.rdoc
5
5
  Rakefile
6
- config/hoe.rb
7
- config/requirements.rb
6
+ TODO
7
+ bin/oauth
8
8
  lib/oauth.rb
9
+ lib/oauth/cli.rb
9
10
  lib/oauth/client.rb
10
11
  lib/oauth/client/action_controller_request.rb
11
12
  lib/oauth/client/helper.rb
12
13
  lib/oauth/client/net_http.rb
13
14
  lib/oauth/consumer.rb
14
15
  lib/oauth/helper.rb
16
+ lib/oauth/oauth_test_helper.rb
15
17
  lib/oauth/request_proxy.rb
16
18
  lib/oauth/request_proxy/action_controller_request.rb
17
19
  lib/oauth/request_proxy/base.rb
20
+ lib/oauth/request_proxy/jabber_request.rb
21
+ lib/oauth/request_proxy/mock_request.rb
18
22
  lib/oauth/request_proxy/net_http.rb
19
23
  lib/oauth/request_proxy/rack_request.rb
20
24
  lib/oauth/server.rb
@@ -31,13 +35,22 @@ lib/oauth/signature/rsa/sha1.rb
31
35
  lib/oauth/signature/sha1.rb
32
36
  lib/oauth/token.rb
33
37
  lib/oauth/version.rb
38
+ oauth.gemspec
34
39
  script/destroy
35
40
  script/generate
36
41
  script/txt2html
37
42
  setup.rb
43
+ specs.txt
38
44
  tasks/deployment.rake
39
45
  tasks/environment.rake
40
46
  tasks/website.rake
47
+ test/cases/oauth_case.rb
48
+ test/cases/spec/1_0-final/test_construct_request_url.rb
49
+ test/cases/spec/1_0-final/test_normalize_request_parameters.rb
50
+ test/cases/spec/1_0-final/test_parameter_encodings.rb
51
+ test/cases/spec/1_0-final/test_signature_base_strings.rb
52
+ test/keys/rsa.cert
53
+ test/keys/rsa.pem
41
54
  test/test_action_controller_request_proxy.rb
42
55
  test/test_consumer.rb
43
56
  test/test_helper.rb
@@ -45,8 +58,11 @@ test/test_hmac_sha1.rb
45
58
  test/test_net_http_client.rb
46
59
  test/test_net_http_request_proxy.rb
47
60
  test/test_rack_request_proxy.rb
61
+ test/test_rsa_sha1.rb
62
+ test/test_server.rb
48
63
  test/test_signature.rb
49
64
  test/test_signature_base.rb
65
+ test/test_signature_plain_text.rb
50
66
  test/test_token.rb
51
67
  website/index.html
52
68
  website/index.txt
File without changes
data/Rakefile CHANGED
@@ -1,4 +1,34 @@
1
- require 'config/requirements'
2
- require 'config/hoe' # setup Hoe + all gem configuration
3
-
4
- Dir['tasks/**/*.rake'].each { |rake| load rake }
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ $LOAD_PATH << File.dirname(__FILE__) + '/lib'
3
+ require 'oauth'
4
+ require 'oauth/version'
5
+
6
+ # Generate all the Rake tasks
7
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
8
+ $hoe = Hoe.new('oauth', OAuth::VERSION) do |p|
9
+ p.author = ['Pelle Braendgaard','Blaine Cook','Larry Halff','Jesse Clark','Jon Crosby', 'Seth Fitzsimmons']
10
+ p.email = "pelleb@gmail.com"
11
+ p.description = "OAuth Core Ruby implementation"
12
+ p.summary = p.description
13
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
14
+ p.rubyforge_name = p.name # TODO this is default value
15
+ p.url = "http://oauth.rubyforge.org"
16
+
17
+ p.extra_deps = [
18
+ ['ruby-hmac','>= 0.3.1']
19
+ ]
20
+ p.extra_dev_deps = [
21
+ ['newgem', ">= #{::Newgem::VERSION}"]
22
+ ]
23
+
24
+ p.clean_globs |= %w[**/.DS_Store tmp *.log **/.*.sw? *.gem .config **/.DS_Store]
25
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
26
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
27
+ p.rsync_args = '-av --delete --ignore-errors'
28
+ end
29
+
30
+ require 'newgem/tasks' # load /tasks/*.rake
31
+ Dir['tasks/**/*.rake'].each { |t| load t }
32
+
33
+ # TODO - want other tests/tasks run by default? Add them to the list
34
+ # task :default => [:spec, :features]
data/TODO ADDED
@@ -0,0 +1,14 @@
1
+ Common use-cases should be streamlined:
2
+
3
+ * I have a URL that I want to sign (given consumer key/secret, optional
4
+ token/secret, optional nonce/timestamp).
5
+ * I have a URL that I want to sign AND I want to see what the components
6
+ (e.g. signature base string, etc.) are while it's being signed (i.e. verbose
7
+ signing).
8
+ * I have a URL that I want to sign and I only want the signature.
9
+ * I have a URL that I want to sign and I want something suitable to put in
10
+ {the header, the querystring, XMPP}.
11
+ * I want to make a query to an OAuth-enabled web service (with sensible
12
+ errors, if available).
13
+ * I want to host an OAuth-enabled web service.
14
+ * I want to test my OAuth-enabled web service (i.e. test helpers)
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "oauth/cli"
4
+
5
+ OAuth::CLI.execute(STDOUT, ARGV)
@@ -1,3 +1,3 @@
1
- $:.unshift File.dirname(__FILE__)
2
-
3
- module OAuth; end
1
+ require 'oauth/client/helper'
2
+ require 'oauth/signature/hmac/sha1'
3
+ require 'oauth/request_proxy/mock_request'
@@ -0,0 +1,130 @@
1
+ require 'optparse'
2
+ require 'oauth'
3
+
4
+ module OAuth
5
+ class CLI
6
+ SUPPORTED_COMMANDS = %w(sign)
7
+
8
+ attr_reader :command
9
+ attr_reader :options
10
+ attr_reader :stdout
11
+
12
+ def self.execute(stdout, arguments = [])
13
+ self.new.execute(stdout, arguments)
14
+ end
15
+
16
+ def execute(stdout, arguments = [])
17
+ @stdout = stdout
18
+ extract_command_and_parse_options(arguments)
19
+
20
+ if sufficient_options? && valid_command?
21
+ case command
22
+ when "sign"
23
+ request = OAuth::RequestProxy.proxy \
24
+ "method" => options[:method],
25
+ "uri" => options[:uri],
26
+ "parameters" => prepare_parameters
27
+
28
+ # can't pass options unless they respond to :secret, so use this alternative
29
+ signature = OAuth::Signature.sign \
30
+ request,
31
+ :consumer_secret => options[:oauth_consumer_secret],
32
+ :token_secret => options[:oauth_token_secret] do |request|
33
+
34
+ # while we have access to the request being signed, display some internals
35
+ if verbose?
36
+ stdout.puts "Method: #{request.method}"
37
+ stdout.puts "URI: #{request.uri}"
38
+ stdout.puts "Normalized params: #{request.normalized_parameters}"
39
+ stdout.puts "Signature base string: #{request.signature_base_string}"
40
+ end
41
+ end
42
+
43
+ if verbose?
44
+ stdout.puts "Signature: #{signature}"
45
+ stdout.puts "Escaped signature: #{OAuth::Helper.escape(signature)}"
46
+ else
47
+ stdout.puts signature
48
+ end
49
+ end
50
+ else
51
+ usage
52
+ end
53
+ end
54
+
55
+ def extract_command_and_parse_options(arguments)
56
+ @command = arguments[-1]
57
+ parse_options(arguments[0..-1])
58
+ end
59
+
60
+ def parse_options(arguments)
61
+ @options = {}
62
+ OptionParser.new do |opts|
63
+ opts.banner = "Usage: #{$0} [options] <command>"
64
+
65
+ # defaults
66
+ options[:oauth_signature_method] = "HMAC-SHA1"
67
+
68
+ opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
69
+ options[:oauth_consumer_key] = v
70
+ end
71
+
72
+ opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
73
+ options[:oauth_consumer_secret] = v
74
+ end
75
+
76
+ opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
77
+ options[:method] = v
78
+ end
79
+
80
+ opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
81
+ options[:params] = v
82
+ end
83
+
84
+ opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
85
+ options[:oauth_signature_method] = v
86
+ end
87
+
88
+ opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
89
+ options[:oauth_token_secret] = v
90
+ end
91
+
92
+ opts.on("--token TOKEN", "Specifies the token to use.") do |v|
93
+ options[:oauth_token] = v
94
+ end
95
+
96
+ opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
97
+ options[:uri] = v
98
+ end
99
+
100
+ opts.on("-v", "--verbose", "Be verbose.") do
101
+ options[:verbose] = true
102
+ end
103
+ end.parse!(arguments)
104
+ end
105
+
106
+ def prepare_parameters
107
+ {
108
+ "oauth_consumer_key" => options[:oauth_consumer_key],
109
+ "oauth_token" => options[:oauth_token],
110
+ "oauth_signature_method" => options[:oauth_signature_method]
111
+ }.merge(CGI.parse(options[:params]))
112
+ end
113
+
114
+ def sufficient_options?
115
+ options[:oauth_consumer_key] && options[:oauth_consumer_secret] && options[:method] && options[:uri]
116
+ end
117
+
118
+ def usage
119
+ stdout.puts "Should be generated by OptionParser"
120
+ end
121
+
122
+ def valid_command?
123
+ SUPPORTED_COMMANDS.include?(command)
124
+ end
125
+
126
+ def verbose?
127
+ options[:verbose]
128
+ end
129
+ end
130
+ end
@@ -38,7 +38,7 @@ module OAuth::Client
38
38
  'oauth_timestamp' => timestamp,
39
39
  'oauth_nonce' => nonce,
40
40
  'oauth_version' => '1.0'
41
- }
41
+ }.reject { |k,v| v == "" }
42
42
  end
43
43
 
44
44
  def signature(extra_options = {})
@@ -60,7 +60,8 @@ module OAuth::Client
60
60
 
61
61
  header_params_str = parameters.map { |k,v| "#{k}=\"#{escape(v)}\"" }.join(', ')
62
62
 
63
- return "OAuth realm=\"#{options[:realm]||''}\", #{header_params_str}"
63
+ realm = "realm=\"#{options[:realm]}\", " if options[:realm]
64
+ "OAuth #{realm}#{header_params_str}"
64
65
  end
65
66
 
66
67
  def parameters
@@ -91,7 +91,7 @@ module OAuth
91
91
  # @request_token=@consumer.get_request_token
92
92
  #
93
93
  def get_request_token(request_options={}, *arguments)
94
- response=token_request(http_method,request_token_path, nil, request_options, *arguments)
94
+ response=token_request(http_method,request_token_url, nil, request_options, *arguments)
95
95
  OAuth::RequestToken.new(self,response[:oauth_token],response[:oauth_token_secret])
96
96
  end
97
97
 
@@ -1,7 +1,10 @@
1
1
  require 'openssl'
2
2
  require 'base64'
3
+ require 'cgi'
3
4
  module OAuth
4
5
  module Helper
6
+ extend self
7
+
5
8
  def escape(value)
6
9
  CGI.escape(value.to_s).gsub("%7E", '~').gsub("+", "%20")
7
10
  end
@@ -0,0 +1,26 @@
1
+ require 'action_controller'
2
+ require 'action_controller/test_process'
3
+ module OAuth
4
+ module OAuthTestHelper
5
+
6
+ def mock_incoming_request_with_query(request)
7
+ incoming=ActionController::TestRequest.new(request.to_hash)
8
+ incoming.request_uri=request.path
9
+ incoming.env["SERVER_PORT"]=request.uri.port
10
+ incoming.host=request.uri.host
11
+ incoming.env['REQUEST_METHOD']=request.http_method
12
+ incoming
13
+ end
14
+
15
+ def mock_incoming_request_with_authorize_header(request)
16
+ incoming=ActionController::TestRequest.new
17
+ incoming.env["HTTP_AUTHORIZATION"]=request.to_auth_string
18
+ incoming.request_uri=request.path
19
+ incoming.env["SERVER_PORT"]=request.uri.port
20
+ incoming.host=request.uri.host
21
+ incoming.env['REQUEST_METHOD']=request.http_method
22
+ incoming
23
+ end
24
+
25
+ end
26
+ end
@@ -6,16 +6,14 @@ require 'uri'
6
6
 
7
7
  module OAuth::RequestProxy
8
8
  class ActionControllerRequest < OAuth::RequestProxy::Base
9
- proxies ActionController::AbstractRequest
9
+ proxies(defined?(ActionController::AbstractRequest) ? ActionController::AbstractRequest : ActionController::Request)
10
10
 
11
11
  def method
12
12
  request.method.to_s.upcase
13
13
  end
14
14
 
15
15
  def uri
16
- uri = URI.parse(request.protocol + request.host + request.port_string + request.path)
17
- uri.query = nil
18
- uri.to_s
16
+ request.url
19
17
  end
20
18
 
21
19
  def parameters
@@ -1,7 +1,10 @@
1
1
  require 'oauth/request_proxy'
2
+ require 'oauth/helper'
2
3
 
3
4
  module OAuth::RequestProxy
4
5
  class Base
6
+ include OAuth::Helper
7
+
5
8
  def self.proxies(klass)
6
9
  OAuth::RequestProxy.available_proxies[klass] = self
7
10
  end
@@ -47,6 +50,34 @@ module OAuth::RequestProxy
47
50
  parameters['oauth_signature'] || ""
48
51
  end
49
52
 
53
+ # See 9.1.2 in specs
54
+ def normalized_uri
55
+ u=URI.parse(uri)
56
+ "#{u.scheme.downcase}://#{u.host.downcase}#{(u.scheme.downcase=='http'&&u.port!=80)||(u.scheme.downcase=='https'&&u.port!=443) ? ":#{u.port}" : ""}#{(u.path&&u.path!='') ? u.path : '/'}"
57
+ end
58
+
59
+ # See 9.1.1. in specs Normalize Request Parameters
60
+ def normalized_parameters
61
+ parameters_for_signature.sort.map do |k, values|
62
+
63
+ if values.is_a?(Array)
64
+ # multiple values were provided for a single key
65
+ values.sort.collect do |v|
66
+ [escape(k),escape(v)] * "="
67
+ end
68
+ else
69
+ [escape(k),escape(values)] * "="
70
+ end
71
+ end * "&"
72
+ end
73
+
74
+ # See 9.1 in specs
75
+ def signature_base_string
76
+ base = [method, normalized_uri, normalized_parameters]
77
+ base.map { |v| escape(v) }.join("&")
78
+ end
79
+
80
+
50
81
  protected
51
82
 
52
83
  def header_params
@@ -0,0 +1,42 @@
1
+ require 'xmpp4r'
2
+ require 'oauth/request_proxy/base'
3
+
4
+ module OAuth
5
+ module RequestProxy
6
+ class JabberRequest < OAuth::RequestProxy::Base
7
+ proxies Jabber::Iq
8
+ proxies Jabber::Presence
9
+ proxies Jabber::Message
10
+
11
+ def parameters
12
+ return @params if @params
13
+
14
+ @params = {}
15
+
16
+ oauth = @request.get_elements('//oauth').first
17
+ return @params unless oauth
18
+
19
+ %w( oauth_token oauth_consumer_key oauth_signature_method oauth_signature
20
+ oauth_timestamp oauth_nonce oauth_version ).each do |param|
21
+ next unless element = oauth.first_element(param)
22
+ @params[param] = element.text
23
+ end
24
+
25
+ @params
26
+ end
27
+
28
+ def method
29
+ @request.name
30
+ end
31
+
32
+ def uri
33
+ [@request.from.strip.to_s, @request.to.strip.to_s].join("&")
34
+ end
35
+
36
+ def normalized_uri
37
+ uri
38
+ end
39
+
40
+ end
41
+ end
42
+ end