oauth 0.5.14 → 0.6.2

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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -3
  3. data/README.md +56 -46
  4. data/SECURITY.md +0 -2
  5. data/bin/oauth +8 -4
  6. data/lib/oauth/cli/authorize_command.rb +58 -54
  7. data/lib/oauth/cli/base_command.rb +163 -159
  8. data/lib/oauth/cli/help_command.rb +9 -5
  9. data/lib/oauth/cli/query_command.rb +26 -17
  10. data/lib/oauth/cli/sign_command.rb +58 -52
  11. data/lib/oauth/cli/version_command.rb +8 -4
  12. data/lib/oauth/cli.rb +2 -0
  13. data/lib/oauth/client/action_controller_request.rb +4 -1
  14. data/lib/oauth/client/em_http.rb +3 -1
  15. data/lib/oauth/client/helper.rb +76 -72
  16. data/lib/oauth/client/net_http.rb +111 -104
  17. data/lib/oauth/client.rb +2 -0
  18. data/lib/oauth/consumer.rb +89 -68
  19. data/lib/oauth/errors/error.rb +2 -0
  20. data/lib/oauth/errors/problem.rb +3 -0
  21. data/lib/oauth/errors/unauthorized.rb +4 -0
  22. data/lib/oauth/errors.rb +2 -0
  23. data/lib/oauth/helper.rb +9 -5
  24. data/lib/oauth/oauth.rb +4 -2
  25. data/lib/oauth/oauth_test_helper.rb +2 -0
  26. data/lib/oauth/request_proxy/base.rb +4 -4
  27. data/lib/oauth/request_proxy/mock_request.rb +1 -1
  28. data/lib/oauth/request_proxy/net_http.rb +8 -8
  29. data/lib/oauth/request_proxy/rest_client_request.rb +4 -3
  30. data/lib/oauth/request_proxy.rb +4 -1
  31. data/lib/oauth/server.rb +8 -4
  32. data/lib/oauth/signature/base.rb +73 -65
  33. data/lib/oauth/signature/hmac/sha1.rb +15 -9
  34. data/lib/oauth/signature/hmac/sha256.rb +15 -9
  35. data/lib/oauth/signature/plaintext.rb +18 -20
  36. data/lib/oauth/signature/rsa/sha1.rb +46 -38
  37. data/lib/oauth/signature.rb +3 -0
  38. data/lib/oauth/token.rb +2 -0
  39. data/lib/oauth/tokens/access_token.rb +2 -0
  40. data/lib/oauth/tokens/consumer_token.rb +2 -0
  41. data/lib/oauth/tokens/request_token.rb +5 -2
  42. data/lib/oauth/tokens/server_token.rb +2 -0
  43. data/lib/oauth/tokens/token.rb +2 -0
  44. data/lib/oauth/version.rb +5 -1
  45. data/lib/oauth.rb +9 -2
  46. metadata +43 -32
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "net/http"
2
4
  require "net/https"
3
5
  require "oauth/oauth"
@@ -17,7 +19,8 @@ module OAuth
17
19
  end
18
20
 
19
21
  unless defined?(CA_FILE)
20
- CA_FILES = %w[/etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt /usr/share/curl/curl-ca-bundle.crt].freeze
22
+ CA_FILES = %w[/etc/ssl/certs/ca-certificates.crt /etc/pki/tls/certs/ca-bundle.crt
23
+ /usr/share/curl/curl-ca-bundle.crt].freeze
21
24
  CA_FILES.each do |ca_file|
22
25
  if File.exist?(ca_file)
23
26
  CA_FILE = ca_file
@@ -27,42 +30,49 @@ module OAuth
27
30
  end
28
31
  CA_FILE = nil unless defined?(CA_FILE)
29
32
 
30
- @@default_options = {
31
- # Signature method used by server. Defaults to HMAC-SHA1
32
- signature_method: "HMAC-SHA1",
33
-
34
- # default paths on site. These are the same as the defaults set up by the generators
35
- request_token_path: "/oauth/request_token",
36
- authenticate_path: "/oauth/authenticate",
37
- authorize_path: "/oauth/authorize",
38
- access_token_path: "/oauth/access_token",
39
-
40
- proxy: nil,
41
- # How do we send the oauth values to the server see
42
- # https://oauth.net/core/1.0/#consumer_req_param for more info
43
- #
44
- # Possible values:
45
- #
46
- # :header - via the Authorize header (Default) ( option 1. in spec)
47
- # :body - url form encoded in body of POST request ( option 2. in spec)
48
- # :query_string - via the query part of the url ( option 3. in spec)
49
- scheme: :header,
50
-
51
- # Default http method used for OAuth Token Requests (defaults to :post)
52
- http_method: :post,
53
-
54
- # Add a custom ca_file for consumer
55
- # :ca_file => '/etc/certs.pem'
56
-
57
- # Possible values:
58
- #
59
- # nil, false - no debug output
60
- # true - uses $stdout
61
- # some_value - uses some_value
62
- debug_output: nil,
63
-
64
- oauth_version: "1.0"
65
- }
33
+ @@default_options = SnakyHash::SymbolKeyed.new(
34
+ {
35
+ # Signature method used by server. Defaults to HMAC-SHA1
36
+ signature_method: "HMAC-SHA1",
37
+
38
+ # default paths on site. These are the same as the defaults set up by the generators
39
+ request_token_path: "/oauth/request_token",
40
+ authenticate_path: "/oauth/authenticate",
41
+ authorize_path: "/oauth/authorize",
42
+ access_token_path: "/oauth/access_token",
43
+
44
+ proxy: nil,
45
+ # How do we send the oauth values to the server see
46
+ # https://oauth.net/core/1.0/#consumer_req_param for more info
47
+ #
48
+ # Possible values:
49
+ #
50
+ # :header - via the Authorize header (Default) ( option 1. in spec)
51
+ # :body - url form encoded in body of POST request ( option 2. in spec)
52
+ # :query_string - via the query part of the url ( option 3. in spec)
53
+ scheme: :header,
54
+
55
+ # Default http method used for OAuth Token Requests (defaults to :post)
56
+ http_method: :post,
57
+
58
+ # Add a custom ca_file for consumer
59
+ # :ca_file => '/etc/certs.pem'
60
+
61
+ # Possible values:
62
+ #
63
+ # nil, false - no debug output
64
+ # true - uses $stdout
65
+ # some_value - uses some_value
66
+ debug_output: nil,
67
+
68
+ # Defaults to producing a body_hash as part of the signature but
69
+ # can be disabled since it's not officially part of the OAuth 1.0
70
+ # spec. Possible values are true and false
71
+ body_hash_enabled: true,
72
+
73
+ oauth_version: "1.0"
74
+ }
75
+ )
66
76
 
67
77
  attr_accessor :options, :key, :secret
68
78
  attr_writer :site, :http
@@ -75,7 +85,8 @@ module OAuth
75
85
  # :http_method => :post,
76
86
  # :request_token_path => "/oauth/example/request_token.php",
77
87
  # :access_token_path => "/oauth/example/access_token.php",
78
- # :authorize_path => "/oauth/example/authorize.php"
88
+ # :authorize_path => "/oauth/example/authorize.php",
89
+ # :body_hash_enabled => false
79
90
  # })
80
91
  #
81
92
  # Start the process by requesting a token
@@ -94,9 +105,8 @@ module OAuth
94
105
  @secret = consumer_secret
95
106
 
96
107
  # ensure that keys are symbols
97
- @options = @@default_options.merge(options.each_with_object({}) do |(key, value), opts|
98
- opts[key.to_sym] = value
99
- end)
108
+ snaky_options = SnakyHash::SymbolKeyed.new(options)
109
+ @options = @@default_options.merge(snaky_options)
100
110
  end
101
111
 
102
112
  # The default http method
@@ -105,15 +115,13 @@ module OAuth
105
115
  end
106
116
 
107
117
  def debug_output
108
- @debug_output ||= begin
109
- case @options[:debug_output]
110
- when nil, false
111
- when true
112
- $stdout
113
- else
114
- @options[:debug_output]
115
- end
116
- end
118
+ @debug_output ||= case @options[:debug_output]
119
+ when nil, false
120
+ when true
121
+ $stdout
122
+ else
123
+ @options[:debug_output]
124
+ end
117
125
  end
118
126
 
119
127
  # The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
@@ -132,7 +140,8 @@ module OAuth
132
140
  end
133
141
 
134
142
  def get_access_token(request_token, request_options = {}, *arguments, &block)
135
- response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token, request_options, *arguments, &block)
143
+ response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token,
144
+ request_options, *arguments, &block)
136
145
  OAuth::AccessToken.from_hash(self, response)
137
146
  end
138
147
 
@@ -153,9 +162,11 @@ module OAuth
153
162
  def get_request_token(request_options = {}, *arguments, &block)
154
163
  # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
155
164
  # will be exchanged out of band
156
- request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
165
+ unless request_options[:exclude_callback]
166
+ request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
167
+ end
157
168
 
158
- response = if block_given?
169
+ response = if block
159
170
  token_request(
160
171
  http_method,
161
172
  (request_token_url? ? request_token_url : request_token_path),
@@ -165,7 +176,8 @@ module OAuth
165
176
  &block
166
177
  )
167
178
  else
168
- token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
179
+ token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil,
180
+ request_options, *arguments)
169
181
  end
170
182
  OAuth::RequestToken.from_hash(self, response)
171
183
  end
@@ -181,7 +193,7 @@ module OAuth
181
193
  # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
182
194
  #
183
195
  def request(http_method, path, token = nil, request_options = {}, *arguments)
184
- if path !~ /^\//
196
+ unless %r{^/}.match?(path)
185
197
  @http = create_http(path)
186
198
  _uri = URI.parse(path)
187
199
  path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
@@ -190,13 +202,14 @@ module OAuth
190
202
  # override the request with your own, this is useful for file uploads which Net::HTTP does not do
191
203
  req = create_signed_request(http_method, path, token, request_options, *arguments)
192
204
  return nil if block_given? && (yield(req) == :done)
205
+
193
206
  rsp = http.request(req)
194
207
  # check for an error reported by the Problem Reporting extension
195
208
  # (https://wiki.oauth.net/ProblemReporting)
196
209
  # note: a 200 may actually be an error; check for an oauth_problem key to be sure
197
210
  if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
198
- (h = headers.select { |hdr| hdr =~ /^OAuth / }).any? &&
199
- h.first =~ /oauth_problem/
211
+ (h = headers.grep(/^OAuth /)).any? &&
212
+ h.first.include?("oauth_problem")
200
213
 
201
214
  # puts "Header: #{h.first}"
202
215
 
@@ -276,6 +289,7 @@ module OAuth
276
289
 
277
290
  def request_endpoint
278
291
  return nil if @options[:request_endpoint].nil?
292
+
279
293
  @options[:request_endpoint].to_s
280
294
  end
281
295
 
@@ -301,7 +315,7 @@ module OAuth
301
315
 
302
316
  # TODO: this is ugly, rewrite
303
317
  def request_token_url
304
- @options[:request_token_url] || site + request_token_path
318
+ @options[:request_token_url] || (site + request_token_path)
305
319
  end
306
320
 
307
321
  def request_token_url?
@@ -309,7 +323,7 @@ module OAuth
309
323
  end
310
324
 
311
325
  def authenticate_url
312
- @options[:authenticate_url] || site + authenticate_path
326
+ @options[:authenticate_url] || (site + authenticate_path)
313
327
  end
314
328
 
315
329
  def authenticate_url?
@@ -317,7 +331,7 @@ module OAuth
317
331
  end
318
332
 
319
333
  def authorize_url
320
- @options[:authorize_url] || site + authorize_path
334
+ @options[:authorize_url] || (site + authorize_path)
321
335
  end
322
336
 
323
337
  def authorize_url?
@@ -325,7 +339,7 @@ module OAuth
325
339
  end
326
340
 
327
341
  def access_token_url
328
- @options[:access_token_url] || site + access_token_path
342
+ @options[:access_token_url] || (site + access_token_path)
329
343
  end
330
344
 
331
345
  def access_token_url?
@@ -342,7 +356,7 @@ module OAuth
342
356
  def create_http(_url = nil)
343
357
  _url = request_endpoint unless request_endpoint.nil?
344
358
 
345
- our_uri = if _url.nil? || _url[0] =~ /^\//
359
+ our_uri = if _url.nil? || _url[0] =~ %r{^/}
346
360
  URI.parse(site)
347
361
  else
348
362
  your_uri = URI.parse(_url)
@@ -359,7 +373,8 @@ module OAuth
359
373
  http_object = Net::HTTP.new(our_uri.host, our_uri.port)
360
374
  else
361
375
  proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
362
- http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
376
+ http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user,
377
+ proxy_uri.password)
363
378
  end
364
379
 
365
380
  http_object.use_ssl = (our_uri.scheme == "https")
@@ -374,10 +389,14 @@ module OAuth
374
389
  end
375
390
 
376
391
  http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 60
377
- http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
392
+ if @options[:open_timeout]
393
+ http_object.open_timeout = @options[:open_timeout]
394
+ end
378
395
  http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
379
- http_object.cert = @options[:ssl_client_cert] if @options[:ssl_client_cert]
380
- http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
396
+ if @options[:ssl_client_cert]
397
+ http_object.cert = @options[:ssl_client_cert]
398
+ end
399
+ http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
381
400
  http_object.set_debug_output(debug_output) if debug_output
382
401
 
383
402
  http_object
@@ -392,8 +411,10 @@ module OAuth
392
411
  # if the base site contains a path, add it now
393
412
  # only add if the site host matches the current http object's host
394
413
  # (in case we've specified a full url for token requests)
395
- uri = URI.parse(site)
396
- path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
414
+ uri = URI.parse(site)
415
+ if uri.path && uri.path != "/" && uri.host == http.address
416
+ path = uri.path + path
417
+ end
397
418
 
398
419
  headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
399
420
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  class Error < StandardError
3
5
  end
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  class Problem < OAuth::Unauthorized
3
5
  attr_reader :problem, :params
6
+
4
7
  def initialize(problem, request = nil, params = {})
5
8
  super(request)
6
9
  @problem = problem
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  class Unauthorized < OAuth::Error
3
5
  attr_reader :request
6
+
4
7
  def initialize(request = nil)
8
+ super()
5
9
  @request = request
6
10
  end
7
11
 
data/lib/oauth/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "oauth/errors/error"
2
4
  require "oauth/errors/unauthorized"
3
5
  require "oauth/errors/problem"
data/lib/oauth/helper.rb CHANGED
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
1
4
  require "openssl"
2
5
  require "base64"
3
6
 
4
7
  module OAuth
5
8
  module Helper
6
- extend self
9
+ module_function
7
10
 
8
11
  # Escape +value+ by URL encoding all non-reserved character.
9
12
  #
@@ -30,7 +33,7 @@ module OAuth
30
33
 
31
34
  alias generate_nonce generate_key
32
35
 
33
- def generate_timestamp #:nodoc:
36
+ def generate_timestamp # :nodoc:
34
37
  Time.now.to_i.to_s
35
38
  end
36
39
 
@@ -43,7 +46,8 @@ module OAuth
43
46
  # See Also: {OAuth core spec version 1.0, section 9.1.1}[http://oauth.net/core/1.0#rfc.section.9.1.1]
44
47
  def normalize(params)
45
48
  params.sort.map do |k, values|
46
- if values.is_a?(Array)
49
+ case values
50
+ when Array
47
51
  # make sure the array has an element so we don't lose the key
48
52
  values << nil if values.empty?
49
53
  # multiple values were provided for a single key
@@ -54,7 +58,7 @@ module OAuth
54
58
  [escape(k), escape(v)].join("=")
55
59
  end
56
60
  end
57
- elsif values.is_a?(Hash)
61
+ when Hash
58
62
  normalize_nested_query(values, k)
59
63
  else
60
64
  [escape(k), escape(values)].join("=")
@@ -99,7 +103,7 @@ module OAuth
99
103
  # strip and unescape
100
104
  val = unescape(v.strip)
101
105
  # strip quotes
102
- val.sub(/^\"(.*)\"$/, '\1')
106
+ val.sub(/^"(.*)"$/, '\1')
103
107
  end
104
108
 
105
109
  # convert into a Hash
data/lib/oauth/oauth.rb CHANGED
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  # request tokens are passed between the consumer and the provider out of
3
5
  # band (i.e. callbacks cannot be used), per section 6.1.1
4
- OUT_OF_BAND = "oob".freeze
6
+ OUT_OF_BAND = "oob"
5
7
 
6
8
  # required parameters, per sections 6.1.1, 6.3.1, and 7
7
9
  PARAMETERS = %w[oauth_callback oauth_consumer_key oauth_token
@@ -9,5 +11,5 @@ module OAuth
9
11
  oauth_version oauth_signature oauth_body_hash].freeze
10
12
 
11
13
  # reserved character regexp, per section 5.1
12
- RESERVED_CHARACTERS = /[^a-zA-Z0-9\-\.\_\~]/
14
+ RESERVED_CHARACTERS = /[^a-zA-Z0-9\-._~]/.freeze
13
15
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "action_controller"
2
4
  require "action_controller/test_process"
3
5
 
@@ -79,15 +79,15 @@ module OAuth
79
79
  end
80
80
 
81
81
  def parameters_for_signature
82
- parameters.reject { |k, _v| signature_and_unsigned_parameters.include?(k) }
82
+ parameters.select { |k, _v| !signature_and_unsigned_parameters.include?(k) }
83
83
  end
84
84
 
85
85
  def oauth_parameters
86
- parameters.select { |k, _v| OAuth::PARAMETERS.include?(k) }.reject { |_k, v| v == "" }
86
+ parameters.select { |k, v| OAuth::PARAMETERS.include?(k) && !v.nil? && v != "" }
87
87
  end
88
88
 
89
89
  def non_oauth_parameters
90
- parameters.reject { |k, _v| OAuth::PARAMETERS.include?(k) }
90
+ parameters.select { |k, _v| !OAuth::PARAMETERS.include?(k) }
91
91
  end
92
92
 
93
93
  def signature_and_unsigned_parameters
@@ -127,7 +127,7 @@ module OAuth
127
127
  end
128
128
 
129
129
  # URI, including OAuth parameters
130
- def signed_uri(with_oauth = true)
130
+ def signed_uri(with_oauth: true)
131
131
  if signed?
132
132
  params = if with_oauth
133
133
  parameters
@@ -32,7 +32,7 @@ module OAuth
32
32
 
33
33
  def normalized_uri
34
34
  super
35
- rescue
35
+ rescue StandardError
36
36
  # if this is a non-standard URI, it may not parse properly
37
37
  # in that case, assume that it's already been normalized
38
38
  uri
@@ -38,13 +38,11 @@ module OAuth
38
38
  request_params = CGI.parse(query_string)
39
39
  # request_params.each{|k,v| request_params[k] = [nil] if v == []}
40
40
 
41
- if options[:parameters]
42
- options[:parameters].each do |k, v|
43
- if request_params.key?(k) && v
44
- request_params[k] << v
45
- else
46
- request_params[k] = [v]
47
- end
41
+ options[:parameters]&.each do |k, v|
42
+ if request_params.key?(k) && v
43
+ request_params[k] << v
44
+ else
45
+ request_params[k] = [v]
48
46
  end
49
47
  end
50
48
  request_params
@@ -71,7 +69,9 @@ module OAuth
71
69
  end
72
70
 
73
71
  def auth_header_params
74
- return nil unless request["Authorization"] && request["Authorization"][0, 5] == "OAuth"
72
+ unless request["Authorization"] && request["Authorization"][0, 5] == "OAuth"
73
+ return nil
74
+ end
75
75
 
76
76
  request["Authorization"]
77
77
  end
@@ -38,7 +38,8 @@ module OAuth
38
38
 
39
39
  def post_parameters
40
40
  # Post params are only used if posting form data
41
- if method == "POST" || method == "PUT"
41
+ is_form_data = request.payload && request.payload.headers["Content-Type"] == "application/x-www-form-urlencoded"
42
+ if is_form_data && (method == "POST" || method == "PUT")
42
43
  OAuth::Helper.stringify_keys(query_string_to_hash(request.payload.to_s) || {})
43
44
  else
44
45
  {}
@@ -51,9 +52,9 @@ module OAuth
51
52
  query.split("&").inject({}) do |result, q|
52
53
  k, v = q.split("=")
53
54
  if !v.nil?
54
- result.merge(k => v)
55
+ result.merge({ k => v })
55
56
  elsif !result.key?(k)
56
- result.merge(k => true)
57
+ result.merge({ k => true })
57
58
  else
58
59
  result
59
60
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  module RequestProxy
3
- def self.available_proxies #:nodoc:
5
+ def self.available_proxies # :nodoc:
4
6
  @available_proxies ||= {}
5
7
  end
6
8
 
@@ -16,6 +18,7 @@ module OAuth
16
18
  end
17
19
 
18
20
  raise UnknownRequestType, request.class.to_s unless klass
21
+
19
22
  klass.new(request, options)
20
23
  end
21
24
 
data/lib/oauth/server.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "oauth/helper"
2
4
  require "oauth/consumer"
3
5
 
@@ -31,10 +33,12 @@ module OAuth
31
33
  def create_consumer
32
34
  creds = generate_credentials
33
35
  Consumer.new(creds[0], creds[1],
34
- site: base_url,
35
- request_token_path: request_token_path,
36
- authorize_path: authorize_path,
37
- access_token_path: access_token_path)
36
+ {
37
+ site: base_url,
38
+ request_token_path: request_token_path,
39
+ authorize_path: authorize_path,
40
+ access_token_path: access_token_path
41
+ })
38
42
  end
39
43
 
40
44
  def request_token_path