oauth 0.5.0 → 0.5.4

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +13 -2
  3. data/bin/oauth +8 -2
  4. data/lib/oauth.rb +2 -2
  5. data/lib/oauth/cli.rb +37 -359
  6. data/lib/oauth/cli/authorize_command.rb +71 -0
  7. data/lib/oauth/cli/base_command.rb +208 -0
  8. data/lib/oauth/cli/help_command.rb +22 -0
  9. data/lib/oauth/cli/query_command.rb +25 -0
  10. data/lib/oauth/cli/sign_command.rb +81 -0
  11. data/lib/oauth/cli/version_command.rb +7 -0
  12. data/lib/oauth/client/action_controller_request.rb +1 -1
  13. data/lib/oauth/client/em_http.rb +0 -1
  14. data/lib/oauth/client/net_http.rb +0 -1
  15. data/lib/oauth/consumer.rb +26 -3
  16. data/lib/oauth/helper.rb +10 -6
  17. data/lib/oauth/request_proxy/action_controller_request.rb +2 -2
  18. data/lib/oauth/request_proxy/action_dispatch_request.rb +7 -0
  19. data/lib/oauth/request_proxy/base.rb +6 -2
  20. data/lib/oauth/tokens/request_token.rb +4 -4
  21. data/lib/oauth/version.rb +1 -1
  22. metadata +82 -90
  23. data/lib/oauth/core_ext.rb +0 -31
  24. data/test/cases/oauth_case.rb +0 -19
  25. data/test/cases/spec/1_0-final/test_construct_request_url.rb +0 -62
  26. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +0 -88
  27. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +0 -86
  28. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +0 -77
  29. data/test/integration/consumer_test.rb +0 -307
  30. data/test/test_access_token.rb +0 -26
  31. data/test/test_action_controller_request_proxy.rb +0 -157
  32. data/test/test_consumer.rb +0 -226
  33. data/test/test_curb_request_proxy.rb +0 -77
  34. data/test/test_em_http_client.rb +0 -80
  35. data/test/test_em_http_request_proxy.rb +0 -115
  36. data/test/test_helper.rb +0 -33
  37. data/test/test_hmac_sha1.rb +0 -20
  38. data/test/test_net_http_client.rb +0 -298
  39. data/test/test_net_http_request_proxy.rb +0 -72
  40. data/test/test_oauth_helper.rb +0 -94
  41. data/test/test_rack_request_proxy.rb +0 -40
  42. data/test/test_request_token.rb +0 -56
  43. data/test/test_rest_client_request_proxy.rb +0 -81
  44. data/test/test_rsa_sha1.rb +0 -59
  45. data/test/test_server.rb +0 -41
  46. data/test/test_signature.rb +0 -15
  47. data/test/test_signature_base.rb +0 -32
  48. data/test/test_signature_hmac_sha1.rb +0 -40
  49. data/test/test_signature_plain_text.rb +0 -31
  50. data/test/test_token.rb +0 -14
  51. data/test/test_typhoeus_request_proxy.rb +0 -101
@@ -0,0 +1,71 @@
1
+ class OAuth::CLI
2
+ class AuthorizeCommand < BaseCommand
3
+
4
+ def required_options
5
+ [:uri]
6
+ end
7
+
8
+ def _run
9
+ request_token = get_request_token
10
+
11
+ if request_token.callback_confirmed?
12
+ puts "Server appears to support OAuth 1.0a; enabling support."
13
+ options[:version] = "1.0a"
14
+ end
15
+
16
+ puts "Please visit this url to authorize:"
17
+ puts request_token.authorize_url
18
+
19
+ # parameters for OAuth 1.0a
20
+ oauth_verifier = ask_user_for_verifier
21
+
22
+ verbosely_get_access_token(request_token, oauth_verifier)
23
+ end
24
+
25
+ def get_request_token
26
+ consumer = get_consumer
27
+ scope_options = options[:scope] ? { "scope" => options[:scope] } : {}
28
+ consumer.get_request_token({ :oauth_callback => options[:oauth_callback] }, scope_options)
29
+ rescue OAuth::Unauthorized => e
30
+ alert "A problem occurred while attempting to authorize:"
31
+ alert e
32
+ alert e.request.body
33
+ end
34
+
35
+ def get_consumer
36
+ OAuth::Consumer.new \
37
+ options[:oauth_consumer_key],
38
+ options[:oauth_consumer_secret],
39
+ :access_token_url => options[:access_token_url],
40
+ :authorize_url => options[:authorize_url],
41
+ :request_token_url => options[:request_token_url],
42
+ :scheme => options[:scheme],
43
+ :http_method => options[:method].to_s.downcase.to_sym
44
+ end
45
+
46
+
47
+ def ask_user_for_verifier
48
+ if options[:version] == "1.0a"
49
+ puts "Please enter the verification code provided by the SP (oauth_verifier):"
50
+ @stdin.gets.chomp
51
+ else
52
+ puts "Press return to continue..."
53
+ @stdin.gets
54
+ nil
55
+ end
56
+ end
57
+
58
+ def verbosely_get_access_token(request_token, oauth_verifier)
59
+ access_token = request_token.get_access_token(:oauth_verifier => oauth_verifier)
60
+
61
+ puts "Response:"
62
+ access_token.params.each do |k,v|
63
+ puts " #{k}: #{v}" unless k.is_a?(Symbol)
64
+ end
65
+ rescue OAuth::Unauthorized => e
66
+ alert "A problem occurred while attempting to obtain an access token:"
67
+ alert e
68
+ alert e.request.body
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,208 @@
1
+ class OAuth::CLI
2
+ class BaseCommand
3
+ def initialize(stdout, stdin, stderr, arguments)
4
+ @stdout, @stdin, @stderr = stdout, stdin, stderr
5
+
6
+ @options = {}
7
+ option_parser.parse!(arguments)
8
+ end
9
+
10
+ def run
11
+ missing = required_options - options.keys
12
+ if missing.empty?
13
+ _run
14
+ else
15
+ show_missing(missing)
16
+ puts option_parser.help
17
+ end
18
+ end
19
+
20
+ def required_options
21
+ []
22
+ end
23
+
24
+ protected
25
+
26
+ attr_reader :options
27
+
28
+ def show_missing(array)
29
+ array = array.map { |s| "--#{s}" }.join(' ')
30
+ OAuth::CLI.puts_red "Options missing to OAuth CLI: #{array}"
31
+ end
32
+
33
+ def xmpp?
34
+ options[:xmpp]
35
+ end
36
+
37
+ def verbose?
38
+ options[:verbose]
39
+ end
40
+
41
+ def puts(string=nil)
42
+ @stdout.puts(string)
43
+ end
44
+
45
+ def alert(string=nil)
46
+ @stderr.puts(string)
47
+ end
48
+
49
+ def parameters
50
+ @parameters ||= begin
51
+ escaped_pairs = options[:params].collect do |pair|
52
+ if pair =~ /:/
53
+ Hash[*pair.split(":", 2)].collect do |k,v|
54
+ [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
55
+ end
56
+ else
57
+ pair
58
+ end
59
+ end
60
+
61
+ querystring = escaped_pairs * "&"
62
+ cli_params = CGI.parse(querystring)
63
+
64
+ {
65
+ "oauth_consumer_key" => options[:oauth_consumer_key],
66
+ "oauth_nonce" => options[:oauth_nonce],
67
+ "oauth_timestamp" => options[:oauth_timestamp],
68
+ "oauth_token" => options[:oauth_token],
69
+ "oauth_signature_method" => options[:oauth_signature_method],
70
+ "oauth_version" => options[:oauth_version]
71
+ }.reject { |_k,v| v.nil? || v == "" }.merge(cli_params)
72
+ end
73
+ end
74
+
75
+ def option_parser
76
+ @option_parser ||= OptionParser.new do |opts|
77
+ opts.banner = "Usage: oauth <command> [ARGS]"
78
+
79
+ _option_parser_defaults
80
+ _option_parser_common(opts)
81
+ _option_parser_sign_and_query(opts)
82
+ _option_parser_authorization(opts)
83
+ end
84
+ end
85
+
86
+ def _option_parser_defaults
87
+ options[:oauth_nonce] = OAuth::Helper.generate_key
88
+ options[:oauth_signature_method] = "HMAC-SHA1"
89
+ options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
90
+ options[:oauth_version] = "1.0"
91
+ options[:method] = :post
92
+ options[:params] = []
93
+ options[:scheme] = :header
94
+ options[:version] = "1.0"
95
+ end
96
+
97
+ def _option_parser_common(opts)
98
+ ## Common Options
99
+
100
+ opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
101
+ options[:scheme] = :body
102
+ end
103
+
104
+ opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
105
+ options[:oauth_consumer_key] = v
106
+ end
107
+
108
+ opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
109
+ options[:oauth_consumer_secret] = v
110
+ end
111
+
112
+ opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
113
+ options[:scheme] = :header
114
+ end
115
+
116
+ opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
117
+ options[:scheme] = :query_string
118
+ end
119
+
120
+ opts.on("-O", "--options FILE", "Read options from a file") do |v|
121
+ arguments = open(v).readlines.map { |l| l.chomp.split(" ") }.flatten
122
+ options2 = parse_options(arguments)
123
+ options.merge!(options2)
124
+ end
125
+ end
126
+
127
+ def _option_parser_sign_and_query(opts)
128
+ opts.separator("\n options for signing and querying")
129
+
130
+ opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
131
+ options[:method] = v
132
+ end
133
+
134
+ opts.on("--nonce NONCE", "Specifies the nonce to use.") do |v|
135
+ options[:oauth_nonce] = v
136
+ end
137
+
138
+ opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
139
+ options[:params] << v
140
+ end
141
+
142
+ opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
143
+ options[:oauth_signature_method] = v
144
+ end
145
+
146
+ opts.on("--token TOKEN", "Specifies the token to use.") do |v|
147
+ options[:oauth_token] = v
148
+ end
149
+
150
+ opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
151
+ options[:oauth_token_secret] = v
152
+ end
153
+
154
+ opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
155
+ options[:oauth_timestamp] = v
156
+ end
157
+
158
+ opts.on("--realm REALM", "Specifies the realm to use.") do |v|
159
+ options[:realm] = v
160
+ end
161
+
162
+ opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
163
+ options[:uri] = v
164
+ end
165
+
166
+ opts.on("--version [VERSION]", "Specifies the OAuth version to use.") do |v|
167
+ options[:oauth_version] = v
168
+ end
169
+
170
+ opts.on("--no-version", "Omit oauth_version.") do
171
+ options[:oauth_version] = nil
172
+ end
173
+
174
+ opts.on("--xmpp", "Generate XMPP stanzas.") do
175
+ options[:xmpp] = true
176
+ options[:method] ||= "iq"
177
+ end
178
+
179
+ opts.on("-v", "--verbose", "Be verbose.") do
180
+ options[:verbose] = true
181
+ end
182
+ end
183
+
184
+ def _option_parser_authorization(opts)
185
+ opts.separator("\n options for authorization")
186
+
187
+ opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
188
+ options[:access_token_url] = v
189
+ end
190
+
191
+ opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
192
+ options[:authorize_url] = v
193
+ end
194
+
195
+ opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
196
+ options[:oauth_callback] = v
197
+ end
198
+
199
+ opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
200
+ options[:request_token_url] = v
201
+ end
202
+
203
+ opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
204
+ options[:scope] = v
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,22 @@
1
+ class OAuth::CLI
2
+ class HelpCommand < BaseCommand
3
+ def run
4
+ puts <<-EOT
5
+ Usage: oauth COMMAND [ARGS]
6
+
7
+ Available oauth commands are:
8
+ a, authorize Obtain an access token and secret for a user
9
+ q, query Query a protected resource
10
+ s, sign Generate an OAuth signature
11
+
12
+ In addition to those, there are:
13
+ v, version Displays the current version of the library (or --version, -v)
14
+ h, help Displays this help (or --help, -h)
15
+
16
+ Tip: All commands can be run without args for specific help.
17
+
18
+
19
+ EOT
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ class OAuth::CLI
2
+ class QueryCommand < BaseCommand
3
+ extend OAuth::Helper
4
+
5
+ def required_options
6
+ [:oauth_consumer_key, :oauth_consumer_secret, :oauth_token, :oauth_token_secret]
7
+ end
8
+
9
+ def _run
10
+ consumer = OAuth::Consumer.new(options[:oauth_consumer_key], options[:oauth_consumer_secret], scheme: options[:scheme])
11
+
12
+ access_token = OAuth::AccessToken.new(consumer, options[:oauth_token], options[:oauth_token_secret])
13
+
14
+ # append params to the URL
15
+ uri = URI.parse(options[:uri])
16
+ params = parameters.map { |k,v| Array(v).map { |v2| "#{OAuth::Helper.escape(k)}=#{OAuth::Helper.escape(v2)}" } * "&" }
17
+ uri.query = [uri.query, *params].reject { |x| x.nil? } * "&"
18
+ puts uri.to_s
19
+
20
+ response = access_token.request(options[:method].to_s.downcase.to_sym, uri.to_s)
21
+ puts "#{response.code} #{response.message}"
22
+ puts response.body
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,81 @@
1
+ class OAuth::CLI
2
+ class SignCommand < BaseCommand
3
+
4
+ def required_options
5
+ [:oauth_consumer_key, :oauth_consumer_secret, :oauth_token, :oauth_token_secret]
6
+ end
7
+
8
+ def _run
9
+ request = OAuth::RequestProxy.proxy \
10
+ "method" => options[:method],
11
+ "uri" => options[:uri],
12
+ "parameters" => parameters
13
+
14
+ if verbose?
15
+ puts_verbose_parameters(request)
16
+ end
17
+
18
+ request.sign! \
19
+ :consumer_secret => options[:oauth_consumer_secret],
20
+ :token_secret => options[:oauth_token_secret]
21
+
22
+ if verbose?
23
+ puts_verbose_request(request)
24
+ else
25
+ puts request.oauth_signature
26
+ end
27
+ end
28
+
29
+ def puts_verbose_parameters(request)
30
+ puts "OAuth parameters:"
31
+ request.oauth_parameters.each do |k,v|
32
+ puts " " + [k, v] * ": "
33
+ end
34
+ puts
35
+
36
+ if request.non_oauth_parameters.any?
37
+ puts "Parameters:"
38
+ request.non_oauth_parameters.each do |k,v|
39
+ puts " " + [k, v] * ": "
40
+ end
41
+ puts
42
+ end
43
+ end
44
+
45
+ def puts_verbose_request(request)
46
+ puts "Method: #{request.method}"
47
+ puts "URI: #{request.uri}"
48
+ puts "Normalized params: #{request.normalized_parameters}" unless options[:xmpp]
49
+ puts "Signature base string: #{request.signature_base_string}"
50
+
51
+ if xmpp?
52
+ puts
53
+ puts "XMPP Stanza:"
54
+ puts xmpp_output(request)
55
+ puts
56
+ puts "Note: You may want to use bare JIDs in your URI."
57
+ puts
58
+ else
59
+ puts "OAuth Request URI: #{request.signed_uri}"
60
+ puts "Request URI: #{request.signed_uri(false)}"
61
+ puts "Authorization header: #{request.oauth_header(:realm => options[:realm])}"
62
+ end
63
+ puts "Signature: #{request.oauth_signature}"
64
+ puts "Escaped signature: #{OAuth::Helper.escape(request.oauth_signature)}"
65
+ end
66
+
67
+ def xmpp_output(request)
68
+ <<-EOS
69
+ <oauth xmlns='urn:xmpp:oauth:0'>
70
+ <oauth_consumer_key>#{request.oauth_consumer_key}</oauth_consumer_key>
71
+ <oauth_token>#{request.oauth_token}</oauth_token>
72
+ <oauth_signature_method>#{request.oauth_signature_method}</oauth_signature_method>
73
+ <oauth_signature>#{request.oauth_signature}</oauth_signature>
74
+ <oauth_timestamp>#{request.oauth_timestamp}</oauth_timestamp>
75
+ <oauth_nonce>#{request.oauth_nonce}</oauth_nonce>
76
+ <oauth_version>#{request.oauth_version}</oauth_version>
77
+ </oauth>
78
+ EOS
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,7 @@
1
+ class OAuth::CLI
2
+ class VersionCommand < BaseCommand
3
+ def run
4
+ puts "OAuth Gem #{OAuth::VERSION}"
5
+ end
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
- require 'oauth/client/helper'
2
1
  if defined? ActionDispatch
3
2
  require 'oauth/request_proxy/rack_request'
3
+ require 'oauth/request_proxy/action_dispatch_request'
4
4
  require 'action_dispatch/testing/test_process'
5
5
  else
6
6
  require 'oauth/request_proxy/action_controller_request'
@@ -1,6 +1,5 @@
1
1
  require 'em-http'
2
2
  require 'oauth/helper'
3
- require 'oauth/client/helper'
4
3
  require 'oauth/request_proxy/em_http_request'
5
4
 
6
5
  # Extensions for em-http so that we can use consumer.sign! with an EventMachine::HttpClient
@@ -1,5 +1,4 @@
1
1
  require 'oauth/helper'
2
- require 'oauth/client/helper'
3
2
  require 'oauth/request_proxy/net_http'
4
3
 
5
4
  class Net::HTTPGenericRequest
@@ -43,6 +43,13 @@ module OAuth
43
43
  # Add a custom ca_file for consumer
44
44
  # :ca_file => '/etc/certs.pem'
45
45
 
46
+ # Possible values:
47
+ #
48
+ # nil, false - no debug output
49
+ # true - uses $stdout
50
+ # some_value - uses some_value
51
+ :debug_output => nil,
52
+
46
53
  :oauth_version => "1.0"
47
54
  }
48
55
 
@@ -87,6 +94,18 @@ module OAuth
87
94
  @http_method ||= @options[:http_method] || :post
88
95
  end
89
96
 
97
+ def debug_output
98
+ @debug_output ||= begin
99
+ case @options[:debug_output]
100
+ when nil, false
101
+ when true
102
+ $stdout
103
+ else
104
+ @options[:debug_output]
105
+ end
106
+ end
107
+ end
108
+
90
109
  # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
91
110
  def http
92
111
  @http ||= create_http
@@ -210,7 +229,7 @@ module OAuth
210
229
  end
211
230
  when (300..399)
212
231
  # this is a redirect
213
- uri = URI.parse(response.header['location'])
232
+ uri = URI.parse(response['location'])
214
233
  response.error! if uri.path == path # careful of those infinite redirects
215
234
  self.token_request(http_method, uri.path, token, request_options, arguments)
216
235
  when (400..499)
@@ -321,6 +340,8 @@ module OAuth
321
340
 
322
341
  http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 30
323
342
  http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
343
+ http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
344
+ http_object.set_debug_output(debug_output) if debug_output
324
345
 
325
346
  http_object
326
347
  end
@@ -334,8 +355,10 @@ module OAuth
334
355
  end
335
356
 
336
357
  # if the base site contains a path, add it now
337
- uri = URI.parse(site)
338
- path = uri.path + path if uri.path && uri.path != '/'
358
+ # only add if the site host matches the current http object's host
359
+ # (in case we've specified a full url for token requests)
360
+ uri = URI.parse(site)
361
+ path = uri.path + path if uri.path && uri.path != '/' && uri.host == http.address
339
362
 
340
363
  headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
341
364