oauth 0.5.1 → 0.5.2

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +12 -2
  3. data/bin/oauth +8 -2
  4. data/lib/oauth.rb +2 -1
  5. data/lib/oauth/cli.rb +32 -360
  6. data/lib/oauth/cli/authorize_command.rb +71 -0
  7. data/lib/oauth/cli/base_command.rb +203 -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 +0 -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/core_ext.rb +24 -2
  17. data/lib/oauth/helper.rb +10 -6
  18. data/lib/oauth/request_proxy/base.rb +5 -1
  19. data/lib/oauth/version.rb +1 -1
  20. metadata +100 -83
  21. data/test/cases/oauth_case.rb +0 -19
  22. data/test/cases/spec/1_0-final/test_construct_request_url.rb +0 -62
  23. data/test/cases/spec/1_0-final/test_normalize_request_parameters.rb +0 -88
  24. data/test/cases/spec/1_0-final/test_parameter_encodings.rb +0 -86
  25. data/test/cases/spec/1_0-final/test_signature_base_strings.rb +0 -77
  26. data/test/integration/consumer_test.rb +0 -307
  27. data/test/test_access_token.rb +0 -26
  28. data/test/test_action_controller_request_proxy.rb +0 -157
  29. data/test/test_consumer.rb +0 -226
  30. data/test/test_curb_request_proxy.rb +0 -77
  31. data/test/test_em_http_client.rb +0 -80
  32. data/test/test_em_http_request_proxy.rb +0 -115
  33. data/test/test_helper.rb +0 -33
  34. data/test/test_hmac_sha1.rb +0 -20
  35. data/test/test_net_http_client.rb +0 -302
  36. data/test/test_net_http_request_proxy.rb +0 -72
  37. data/test/test_oauth_helper.rb +0 -94
  38. data/test/test_rack_request_proxy.rb +0 -40
  39. data/test/test_request_token.rb +0 -56
  40. data/test/test_rest_client_request_proxy.rb +0 -81
  41. data/test/test_rsa_sha1.rb +0 -59
  42. data/test/test_server.rb +0 -41
  43. data/test/test_signature.rb +0 -15
  44. data/test/test_signature_base.rb +0 -32
  45. data/test/test_signature_hmac_sha1.rb +0 -40
  46. data/test/test_signature_plain_text.rb +0 -31
  47. data/test/test_token.rb +0 -14
  48. 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,203 @@
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
+ # puts "Options missing to OAuth CLI: #{options}"
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 xmpp?
29
+ options[:xmpp]
30
+ end
31
+
32
+ def verbose?
33
+ options[:verbose]
34
+ end
35
+
36
+ def puts(string=nil)
37
+ @stdout.puts(string)
38
+ end
39
+
40
+ def alert(string=nil)
41
+ @stderr.puts(string)
42
+ end
43
+
44
+ def parameters
45
+ @parameters ||= begin
46
+ escaped_pairs = options[:params].collect do |pair|
47
+ if pair =~ /:/
48
+ Hash[*pair.split(":", 2)].collect do |k,v|
49
+ [CGI.escape(k.strip), CGI.escape(v.strip)] * "="
50
+ end
51
+ else
52
+ pair
53
+ end
54
+ end
55
+
56
+ querystring = escaped_pairs * "&"
57
+ cli_params = CGI.parse(querystring)
58
+
59
+ {
60
+ "oauth_consumer_key" => options[:oauth_consumer_key],
61
+ "oauth_nonce" => options[:oauth_nonce],
62
+ "oauth_timestamp" => options[:oauth_timestamp],
63
+ "oauth_token" => options[:oauth_token],
64
+ "oauth_signature_method" => options[:oauth_signature_method],
65
+ "oauth_version" => options[:oauth_version]
66
+ }.reject { |_k,v| v.nil? || v == "" }.merge(cli_params)
67
+ end
68
+ end
69
+
70
+ def option_parser
71
+ @option_parser ||= OptionParser.new do |opts|
72
+ opts.banner = "Usage: oauth <command> [ARGS]"
73
+
74
+ _option_parser_defaults
75
+ _option_parser_common(opts)
76
+ _option_parser_sign_and_query(opts)
77
+ _option_parser_authorization(opts)
78
+ end
79
+ end
80
+
81
+ def _option_parser_defaults
82
+ options[:oauth_nonce] = OAuth::Helper.generate_key
83
+ options[:oauth_signature_method] = "HMAC-SHA1"
84
+ options[:oauth_timestamp] = OAuth::Helper.generate_timestamp
85
+ options[:oauth_version] = "1.0"
86
+ options[:method] = :post
87
+ options[:params] = []
88
+ options[:scheme] = :header
89
+ options[:version] = "1.0"
90
+ end
91
+
92
+ def _option_parser_common(opts)
93
+ ## Common Options
94
+
95
+ opts.on("-B", "--body", "Use the request body for OAuth parameters.") do
96
+ options[:scheme] = :body
97
+ end
98
+
99
+ opts.on("--consumer-key KEY", "Specifies the consumer key to use.") do |v|
100
+ options[:oauth_consumer_key] = v
101
+ end
102
+
103
+ opts.on("--consumer-secret SECRET", "Specifies the consumer secret to use.") do |v|
104
+ options[:oauth_consumer_secret] = v
105
+ end
106
+
107
+ opts.on("-H", "--header", "Use the 'Authorization' header for OAuth parameters (default).") do
108
+ options[:scheme] = :header
109
+ end
110
+
111
+ opts.on("-Q", "--query-string", "Use the query string for OAuth parameters.") do
112
+ options[:scheme] = :query_string
113
+ end
114
+
115
+ opts.on("-O", "--options FILE", "Read options from a file") do |v|
116
+ arguments = open(v).readlines.map { |l| l.chomp.split(" ") }.flatten
117
+ options2 = parse_options(arguments)
118
+ options.merge!(options2)
119
+ end
120
+ end
121
+
122
+ def _option_parser_sign_and_query(opts)
123
+ opts.separator("\n options for signing and querying")
124
+
125
+ opts.on("--method METHOD", "Specifies the method (e.g. GET) to use when signing.") do |v|
126
+ options[:method] = v
127
+ end
128
+
129
+ opts.on("--nonce NONCE", "Specifies the none to use.") do |v|
130
+ options[:oauth_nonce] = v
131
+ end
132
+
133
+ opts.on("--parameters PARAMS", "Specifies the parameters to use when signing.") do |v|
134
+ options[:params] << v
135
+ end
136
+
137
+ opts.on("--signature-method METHOD", "Specifies the signature method to use; defaults to HMAC-SHA1.") do |v|
138
+ options[:oauth_signature_method] = v
139
+ end
140
+
141
+ opts.on("--token TOKEN", "Specifies the token to use.") do |v|
142
+ options[:oauth_token] = v
143
+ end
144
+
145
+ opts.on("--secret SECRET", "Specifies the token secret to use.") do |v|
146
+ options[:oauth_token_secret] = v
147
+ end
148
+
149
+ opts.on("--timestamp TIMESTAMP", "Specifies the timestamp to use.") do |v|
150
+ options[:oauth_timestamp] = v
151
+ end
152
+
153
+ opts.on("--realm REALM", "Specifies the realm to use.") do |v|
154
+ options[:realm] = v
155
+ end
156
+
157
+ opts.on("--uri URI", "Specifies the URI to use when signing.") do |v|
158
+ options[:uri] = v
159
+ end
160
+
161
+ opts.on("--version [VERSION]", "Specifies the OAuth version to use.") do |v|
162
+ options[:oauth_version] = v
163
+ end
164
+
165
+ opts.on("--no-version", "Omit oauth_version.") do
166
+ options[:oauth_version] = nil
167
+ end
168
+
169
+ opts.on("--xmpp", "Generate XMPP stanzas.") do
170
+ options[:xmpp] = true
171
+ options[:method] ||= "iq"
172
+ end
173
+
174
+ opts.on("-v", "--verbose", "Be verbose.") do
175
+ options[:verbose] = true
176
+ end
177
+ end
178
+
179
+ def _option_parser_authorization(opts)
180
+ opts.separator("\n options for authorization")
181
+
182
+ opts.on("--access-token-url URL", "Specifies the access token URL.") do |v|
183
+ options[:access_token_url] = v
184
+ end
185
+
186
+ opts.on("--authorize-url URL", "Specifies the authorization URL.") do |v|
187
+ options[:authorize_url] = v
188
+ end
189
+
190
+ opts.on("--callback-url URL", "Specifies a callback URL.") do |v|
191
+ options[:oauth_callback] = v
192
+ end
193
+
194
+ opts.on("--request-token-url URL", "Specifies the request token URL.") do |v|
195
+ options[:request_token_url] = v
196
+ end
197
+
198
+ opts.on("--scope SCOPE", "Specifies the scope (Google-specific).") do |v|
199
+ options[:scope] = v
200
+ end
201
+ end
202
+ end
203
+ 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 for Ruby #{OAuth::VERSION}"
5
+ end
6
+ end
7
+ end
@@ -1,4 +1,3 @@
1
- require 'oauth/client/helper'
2
1
  if defined? ActionDispatch
3
2
  require 'oauth/request_proxy/rack_request'
4
3
  require 'action_dispatch/testing/test_process'
@@ -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