oauth 0.5.14 → 1.1.6

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 (69) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +1 -0
  3. data/CHANGELOG.md +663 -239
  4. data/CITATION.cff +20 -0
  5. data/CODE_OF_CONDUCT.md +79 -29
  6. data/CONTRIBUTING.md +264 -15
  7. data/FUNDING.md +74 -0
  8. data/LICENSE.md +71 -0
  9. data/README.md +642 -297
  10. data/RUBOCOP.md +71 -0
  11. data/SECURITY.md +11 -12
  12. data/certs/pboling.pem +27 -0
  13. data/lib/oauth/auth_sanitizer.rb +36 -0
  14. data/lib/oauth/client/action_controller_request.rb +24 -12
  15. data/lib/oauth/client/em_http.rb +107 -100
  16. data/lib/oauth/client/helper.rb +80 -72
  17. data/lib/oauth/client/net_http.rb +139 -106
  18. data/lib/oauth/client.rb +2 -0
  19. data/lib/oauth/consumer.rb +250 -118
  20. data/lib/oauth/errors/error.rb +2 -0
  21. data/lib/oauth/errors/problem.rb +4 -1
  22. data/lib/oauth/errors/unauthorized.rb +4 -0
  23. data/lib/oauth/errors.rb +2 -0
  24. data/lib/oauth/helper.rb +34 -8
  25. data/lib/oauth/oauth.rb +32 -8
  26. data/lib/oauth/oauth_test_helper.rb +2 -0
  27. data/lib/oauth/optional.rb +20 -0
  28. data/lib/oauth/request_proxy/action_controller_request.rb +14 -31
  29. data/lib/oauth/request_proxy/action_dispatch_request.rb +34 -0
  30. data/lib/oauth/request_proxy/base.rb +42 -31
  31. data/lib/oauth/request_proxy/em_http_request.rb +53 -52
  32. data/lib/oauth/request_proxy/jabber_request.rb +9 -2
  33. data/lib/oauth/request_proxy/mock_request.rb +1 -1
  34. data/lib/oauth/request_proxy/net_http.rb +6 -8
  35. data/lib/oauth/request_proxy/rack_request.rb +0 -4
  36. data/lib/oauth/request_proxy/rest_client_request.rb +6 -4
  37. data/lib/oauth/request_proxy.rb +20 -13
  38. data/lib/oauth/server.rb +14 -6
  39. data/lib/oauth/signature/base.rb +82 -66
  40. data/lib/oauth/signature/hmac/sha1.rb +15 -9
  41. data/lib/oauth/signature/hmac/sha256.rb +15 -9
  42. data/lib/oauth/signature/plaintext.rb +18 -20
  43. data/lib/oauth/signature/rsa/sha1.rb +53 -38
  44. data/lib/oauth/signature.rb +40 -33
  45. data/lib/oauth/token.rb +2 -0
  46. data/lib/oauth/tokens/access_token.rb +3 -1
  47. data/lib/oauth/tokens/consumer_token.rb +10 -6
  48. data/lib/oauth/tokens/request_token.rb +12 -4
  49. data/lib/oauth/tokens/server_token.rb +2 -0
  50. data/lib/oauth/tokens/token.rb +15 -1
  51. data/lib/oauth/version.rb +6 -1
  52. data/lib/oauth.rb +11 -2
  53. data/sig/oauth/consumer.rbs +9 -0
  54. data/sig/oauth/signature/base.rbs +12 -0
  55. data/sig/oauth/tokens/token.rbs +8 -0
  56. data/sig/oauth/version.rbs +6 -0
  57. data.tar.gz.sig +0 -0
  58. metadata +349 -90
  59. metadata.gz.sig +0 -0
  60. data/LICENSE +0 -21
  61. data/TODO +0 -32
  62. data/bin/oauth +0 -11
  63. data/lib/oauth/cli/authorize_command.rb +0 -69
  64. data/lib/oauth/cli/base_command.rb +0 -210
  65. data/lib/oauth/cli/help_command.rb +0 -22
  66. data/lib/oauth/cli/query_command.rb +0 -25
  67. data/lib/oauth/cli/sign_command.rb +0 -78
  68. data/lib/oauth/cli/version_command.rb +0 -7
  69. data/lib/oauth/cli.rb +0 -56
@@ -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"
@@ -6,7 +8,22 @@ require "oauth/errors"
6
8
  require "cgi"
7
9
 
8
10
  module OAuth
11
+ # Consumer credentials and request configuration for OAuth 1.0 / 1.0a flows.
12
+ #
13
+ # Includes {OAuth::AUTH_SANITIZER::FilteredAttributes} so inspect output redacts the
14
+ # consumer secret while leaving non-sensitive configuration visible.
9
15
  class Consumer
16
+ include OAuth::AUTH_SANITIZER::FilteredAttributes
17
+
18
+ # Instance attributes exposed by the consumer.
19
+ #
20
+ # @!attribute [rw] options
21
+ # @return [Hash] Consumer configuration options
22
+ # @!attribute [rw] key
23
+ # @return [String] OAuth consumer key
24
+ # @!attribute [rw] secret
25
+ # @return [String] OAuth consumer secret (redacted in `#inspect`)
26
+
10
27
  # determine the certificate authority path to verify SSL certs
11
28
  if ENV["SSL_CERT_FILE"]
12
29
  if File.exist?(ENV["SSL_CERT_FILE"])
@@ -17,7 +34,11 @@ module OAuth
17
34
  end
18
35
 
19
36
  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
37
+ CA_FILES = %w[
38
+ /etc/ssl/certs/ca-certificates.crt
39
+ /etc/pki/tls/certs/ca-bundle.crt
40
+ /usr/share/curl/curl-ca-bundle.crt
41
+ ].freeze
21
42
  CA_FILES.each do |ca_file|
22
43
  if File.exist?(ca_file)
23
44
  CA_FILE = ca_file
@@ -27,45 +48,59 @@ module OAuth
27
48
  end
28
49
  CA_FILE = nil unless defined?(CA_FILE)
29
50
 
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
- }
51
+ @@default_options = SnakyHash::SymbolKeyed.new(
52
+ {
53
+ # Signature method used by server. Defaults to HMAC-SHA1
54
+ signature_method: "HMAC-SHA1",
55
+
56
+ # default paths on site. These are the same as the defaults set up by the generators
57
+ request_token_path: "/oauth/request_token",
58
+ authenticate_path: "/oauth/authenticate",
59
+ authorize_path: "/oauth/authorize",
60
+ access_token_path: "/oauth/access_token",
61
+
62
+ proxy: nil,
63
+ # How do we send the oauth values to the server see
64
+ # https://oauth.net/core/1.0/#consumer_req_param for more info
65
+ #
66
+ # Possible values:
67
+ #
68
+ # :header - via the Authorize header (Default) ( option 1. in spec)
69
+ # :body - url form encoded in body of POST request ( option 2. in spec)
70
+ # :query_string - via the query part of the url ( option 3. in spec)
71
+ scheme: :header,
72
+
73
+ # Default http method used for OAuth Token Requests (defaults to :post)
74
+ http_method: :post,
75
+
76
+ # Add a custom ca_file for consumer
77
+ # :ca_file => '/etc/certs.pem'
78
+
79
+ # Possible values:
80
+ #
81
+ # nil, false - no debug output
82
+ # true - uses $stdout
83
+ # some_value - uses some_value
84
+ debug_output: nil,
85
+
86
+ # Defaults to producing a body_hash as part of the signature but
87
+ # can be disabled since it's not officially part of the OAuth 1.0
88
+ # spec. Possible values are true and false
89
+ body_hash_enabled: true,
90
+
91
+ oauth_version: "1.0",
92
+
93
+ # Token endpoint redirects are followed only within the same origin by
94
+ # default. Cross-origin redirects can re-sign token requests for an
95
+ # attacker-controlled endpoint, so they require explicit opt-in.
96
+ token_request_max_redirects: 10,
97
+ token_request_cross_origin_redirects: false,
98
+ },
99
+ )
66
100
 
67
101
  attr_accessor :options, :key, :secret
68
- attr_writer :site, :http
102
+ filtered_attributes :secret
103
+ attr_writer :site, :http
69
104
 
70
105
  # Create a new consumer instance by passing it a configuration hash:
71
106
  #
@@ -75,7 +110,8 @@ module OAuth
75
110
  # :http_method => :post,
76
111
  # :request_token_path => "/oauth/example/request_token.php",
77
112
  # :access_token_path => "/oauth/example/access_token.php",
78
- # :authorize_path => "/oauth/example/authorize.php"
113
+ # :authorize_path => "/oauth/example/authorize.php",
114
+ # :body_hash_enabled => false
79
115
  # })
80
116
  #
81
117
  # Start the process by requesting a token
@@ -90,13 +126,12 @@ module OAuth
90
126
  # @photos=@access_token.get('/photos.xml')
91
127
  #
92
128
  def initialize(consumer_key, consumer_secret, options = {})
93
- @key = consumer_key
129
+ @key = consumer_key
94
130
  @secret = consumer_secret
95
131
 
96
132
  # 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)
133
+ snaky_options = SnakyHash::SymbolKeyed.new(options)
134
+ @options = @@default_options.merge(snaky_options)
100
135
  end
101
136
 
102
137
  # The default http method
@@ -105,14 +140,12 @@ module OAuth
105
140
  end
106
141
 
107
142
  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
143
+ @debug_output ||= case @options[:debug_output]
144
+ when nil, false
145
+ when true
146
+ $stdout
147
+ else
148
+ @options[:debug_output]
116
149
  end
117
150
  end
118
151
 
@@ -124,49 +157,93 @@ module OAuth
124
157
  # Contains the root URI for this site
125
158
  def uri(custom_uri = nil)
126
159
  if custom_uri
127
- @uri = custom_uri
160
+ @uri = custom_uri
128
161
  @http = create_http # yike, oh well. less intrusive this way
129
162
  else # if no custom passed, we use existing, which, if unset, is set to site uri
130
163
  @uri ||= URI.parse(site)
131
164
  end
132
165
  end
133
166
 
167
+ # Exchanges a verified Request Token for an Access Token.
168
+ #
169
+ # OAuth 1.0 vs 1.0a:
170
+ # - 1.0a requires including oauth_verifier (as returned by the Provider after
171
+ # user authorization) when performing this exchange in a 3‑legged flow.
172
+ # - 1.0 flows did not include oauth_verifier.
173
+ #
174
+ # Usage (3‑legged):
175
+ # access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
176
+ #
177
+ # @param request_token [OAuth::RequestToken] The authorized request token
178
+ # @param request_options [Hash] OAuth or request options (include :oauth_verifier for 1.0a)
179
+ # @param arguments [Array] Optional POST body and headers
180
+ # @yield [response_body] If a block is given, yields the raw response body.
181
+ # @return [OAuth::AccessToken]
134
182
  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)
183
+ response = token_request(
184
+ http_method,
185
+ (access_token_url? ? access_token_url : access_token_path),
186
+ request_token,
187
+ request_options,
188
+ *arguments,
189
+ &block
190
+ )
136
191
  OAuth::AccessToken.from_hash(self, response)
137
192
  end
138
193
 
139
194
  # Makes a request to the service for a new OAuth::RequestToken
140
195
  #
141
- # @request_token = @consumer.get_request_token
196
+ # Example:
197
+ # @request_token = @consumer.get_request_token
142
198
  #
143
199
  # To include OAuth parameters:
144
- #
145
- # @request_token = @consumer.get_request_token \
146
- # :oauth_callback => "http://example.com/cb"
200
+ # @request_token = @consumer.get_request_token(
201
+ # oauth_callback: "http://example.com/cb"
202
+ # )
147
203
  #
148
204
  # To include application-specific parameters:
205
+ # @request_token = @consumer.get_request_token({}, foo: "bar")
149
206
  #
150
- # @request_token = @consumer.get_request_token({}, :foo => "bar")
207
+ # OAuth 1.0 vs 1.0a:
208
+ # - In 1.0a, the Consumer SHOULD send oauth_callback when obtaining a request token
209
+ # (or explicitly use OUT_OF_BAND) and the Provider MUST include
210
+ # oauth_callback_confirmed=true in the response.
211
+ # - This library defaults oauth_callback to OUT_OF_BAND ("oob") when not provided,
212
+ # which works for both 1.0 and 1.0a, and mirrors common provider behavior.
213
+ # - The oauth_callback_confirmed response is parsed by the token classes; it is not
214
+ # part of the signature base string and thus is not signed.
151
215
  #
152
- # TODO oauth_callback should be a mandatory parameter
216
+ # TODO: In a future major release, oauth_callback may be made mandatory unless
217
+ # request_options[:exclude_callback] is set, to reflect 1.0a guidance.
218
+ #
219
+ # @param request_options [Hash] OAuth options for the request. Notably
220
+ # :oauth_callback can be set to a URL, or OAuth::OUT_OF_BAND ("oob").
221
+ # @param arguments [Array] Optional POST body and headers
222
+ # @yield [response_body] If a block is given, yields the raw response body.
223
+ # @return [OAuth::RequestToken]
153
224
  def get_request_token(request_options = {}, *arguments, &block)
154
225
  # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
155
226
  # will be exchanged out of band
156
227
  request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
157
228
 
158
- response = if block_given?
159
- token_request(
160
- http_method,
161
- (request_token_url? ? request_token_url : request_token_path),
162
- nil,
163
- request_options,
164
- *arguments,
165
- &block
166
- )
167
- else
168
- token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
169
- end
229
+ response = if block
230
+ token_request(
231
+ http_method,
232
+ (request_token_url? ? request_token_url : request_token_path),
233
+ nil,
234
+ request_options,
235
+ *arguments,
236
+ &block
237
+ )
238
+ else
239
+ token_request(
240
+ http_method,
241
+ (request_token_url? ? request_token_url : request_token_path),
242
+ nil,
243
+ request_options,
244
+ *arguments,
245
+ )
246
+ end
170
247
  OAuth::RequestToken.from_hash(self, response)
171
248
  end
172
249
 
@@ -181,22 +258,23 @@ module OAuth
181
258
  # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
182
259
  #
183
260
  def request(http_method, path, token = nil, request_options = {}, *arguments)
184
- if path !~ /^\//
261
+ unless %r{^/} =~ path
185
262
  @http = create_http(path)
186
- _uri = URI.parse(path)
187
- path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
263
+ uri = URI.parse(path)
264
+ path = "#{uri.path}#{"?#{uri.query}" if uri.query}"
188
265
  end
189
266
 
190
267
  # override the request with your own, this is useful for file uploads which Net::HTTP does not do
191
268
  req = create_signed_request(http_method, path, token, request_options, *arguments)
192
- return nil if block_given? && (yield(req) == :done)
269
+ return if block_given? && (yield(req) == :done)
270
+
193
271
  rsp = http.request(req)
194
272
  # check for an error reported by the Problem Reporting extension
195
273
  # (https://wiki.oauth.net/ProblemReporting)
196
274
  # note: a 200 may actually be an error; check for an oauth_problem key to be sure
197
275
  if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
198
- (h = headers.select { |hdr| hdr =~ /^OAuth / }).any? &&
199
- h.first =~ /oauth_problem/
276
+ (h = headers.grep(/^OAuth /)).any? &&
277
+ h.first.include?("oauth_problem")
200
278
 
201
279
  # puts "Header: #{h.first}"
202
280
 
@@ -222,37 +300,34 @@ module OAuth
222
300
  end
223
301
 
224
302
  # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
225
- def token_request(http_method, path, token = nil, request_options = {}, *arguments)
226
- request_options[:token_request] ||= true
227
- response = request(http_method, path, token, request_options, *arguments)
303
+ def token_request(http_method, path, token = nil, request_options = {}, *arguments, &block)
304
+ response = request(http_method, path, token, token_request_options(request_options), *arguments)
228
305
  case response.code.to_i
229
306
 
230
307
  when (200..299)
231
- if block_given?
232
- yield response.body
308
+ if block
309
+ block.call(response.body)
233
310
  else
234
311
  # symbolize keys
235
312
  # TODO this could be considered unexpected behavior; symbols or not?
236
313
  # TODO this also drops subsequent values from multi-valued keys
237
314
  CGI.parse(response.body).each_with_object({}) do |(k, v), h|
238
315
  h[k.strip.to_sym] = v.first
239
- h[k.strip] = v.first
316
+ h[k.strip] = v.first
240
317
  end
241
318
  end
242
319
  when (300..399)
243
- # Parse redirect to follow
244
- uri = URI.parse(response["location"])
245
- our_uri = URI.parse(site)
246
-
247
- # Guard against infinite redirects
248
- response.error! if uri.path == path && our_uri.host == uri.host
320
+ current_uri = token_request_uri(path)
321
+ redirected_uri = token_request_redirect_uri(current_uri, response)
322
+ response.error! unless redirected_uri
249
323
 
250
- if uri.path == path && our_uri.host != uri.host
251
- options[:site] = "#{uri.scheme}://#{uri.host}"
252
- @http = create_http
253
- end
324
+ redirect_count = request_options[:token_request_redirect_count].to_i + 1
325
+ response.error! if redirect_count > token_request_max_redirects(request_options)
326
+ response.error! if token_request_cross_origin?(current_uri, redirected_uri) &&
327
+ !token_request_cross_origin_redirects?(request_options)
254
328
 
255
- token_request(http_method, uri.path, token, request_options, arguments)
329
+ redirect_options = request_options.merge(token_request_redirect_count: redirect_count)
330
+ token_request(http_method, token_request_redirect_path(current_uri, redirected_uri), token, redirect_options, *arguments, &block)
256
331
  when (400..499)
257
332
  raise OAuth::Unauthorized, response
258
333
  else
@@ -260,6 +335,55 @@ module OAuth
260
335
  end
261
336
  end
262
337
 
338
+ def token_request_options(request_options)
339
+ request_options.merge(token_request: true).tap do |options|
340
+ options.delete(:token_request_redirect_count)
341
+ options.delete(:token_request_max_redirects)
342
+ options.delete(:token_request_cross_origin_redirects)
343
+ end
344
+ end
345
+
346
+ def token_request_uri(path)
347
+ uri = URI.parse(path)
348
+ return uri if uri.absolute?
349
+
350
+ URI.parse(site).merge(path)
351
+ end
352
+
353
+ def token_request_redirect_uri(current_uri, response)
354
+ location = response["location"]
355
+ return if location.nil? || location.to_s.empty?
356
+
357
+ current_uri.merge(location)
358
+ end
359
+
360
+ def token_request_redirect_path(current_uri, redirected_uri)
361
+ return redirected_uri.to_s if token_request_cross_origin?(current_uri, redirected_uri)
362
+
363
+ redirected_uri.request_uri
364
+ end
365
+
366
+ def token_request_max_redirects(request_options)
367
+ request_options[:token_request_max_redirects] || options[:token_request_max_redirects]
368
+ end
369
+
370
+ def token_request_cross_origin_redirects?(request_options)
371
+ request_options.fetch(:token_request_cross_origin_redirects, options[:token_request_cross_origin_redirects])
372
+ end
373
+
374
+ def token_request_cross_origin?(current_uri, redirected_uri)
375
+ current_uri.scheme.to_s.downcase != redirected_uri.scheme.to_s.downcase ||
376
+ current_uri.host.to_s.downcase != redirected_uri.host.to_s.downcase ||
377
+ token_request_effective_port(current_uri) != token_request_effective_port(redirected_uri)
378
+ end
379
+
380
+ def token_request_effective_port(uri)
381
+ return uri.port if uri.port
382
+ return 443 if uri.scheme == "https"
383
+
384
+ 80 if uri.scheme == "http"
385
+ end
386
+
263
387
  # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
264
388
  def sign!(request, token = nil, request_options = {})
265
389
  request.oauth!(http, self, token, options.merge(request_options))
@@ -275,7 +399,8 @@ module OAuth
275
399
  end
276
400
 
277
401
  def request_endpoint
278
- return nil if @options[:request_endpoint].nil?
402
+ return if @options[:request_endpoint].nil?
403
+
279
404
  @options[:request_endpoint].to_s
280
405
  end
281
406
 
@@ -301,7 +426,7 @@ module OAuth
301
426
 
302
427
  # TODO: this is ugly, rewrite
303
428
  def request_token_url
304
- @options[:request_token_url] || site + request_token_path
429
+ @options[:request_token_url] || (site + request_token_path)
305
430
  end
306
431
 
307
432
  def request_token_url?
@@ -309,7 +434,7 @@ module OAuth
309
434
  end
310
435
 
311
436
  def authenticate_url
312
- @options[:authenticate_url] || site + authenticate_path
437
+ @options[:authenticate_url] || (site + authenticate_path)
313
438
  end
314
439
 
315
440
  def authenticate_url?
@@ -317,7 +442,7 @@ module OAuth
317
442
  end
318
443
 
319
444
  def authorize_url
320
- @options[:authorize_url] || site + authorize_path
445
+ @options[:authorize_url] || (site + authorize_path)
321
446
  end
322
447
 
323
448
  def authorize_url?
@@ -325,7 +450,7 @@ module OAuth
325
450
  end
326
451
 
327
452
  def access_token_url
328
- @options[:access_token_url] || site + access_token_path
453
+ @options[:access_token_url] || (site + access_token_path)
329
454
  end
330
455
 
331
456
  def access_token_url?
@@ -339,27 +464,34 @@ module OAuth
339
464
  protected
340
465
 
341
466
  # Instantiates the http object
342
- def create_http(_url = nil)
343
- _url = request_endpoint unless request_endpoint.nil?
344
-
345
- our_uri = if _url.nil? || _url[0] =~ /^\//
346
- URI.parse(site)
347
- else
348
- your_uri = URI.parse(_url)
349
- if your_uri.host.nil?
350
- # If the _url is a path, missing the leading slash, then it won't have a host,
351
- # and our_uri *must* have a host, so we parse site instead.
352
- URI.parse(site)
353
- else
354
- your_uri
355
- end
356
- end
467
+ def create_http(url = nil)
468
+ url = request_endpoint unless request_endpoint.nil?
469
+
470
+ our_uri = if url.nil? || url[0] =~ %r{^/}
471
+ URI.parse(site)
472
+ else
473
+ your_uri = URI.parse(url)
474
+ if your_uri.host.nil?
475
+ # If the _url is a path, missing the leading slash, then it won't have a host,
476
+ # and our_uri *must* have a host, so we parse site instead.
477
+ URI.parse(site)
478
+ else
479
+ your_uri
480
+ end
481
+ end
357
482
 
358
483
  if proxy.nil?
359
484
  http_object = Net::HTTP.new(our_uri.host, our_uri.port)
360
485
  else
361
486
  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)
487
+ http_object = Net::HTTP.new(
488
+ our_uri.host,
489
+ our_uri.port,
490
+ proxy_uri.host,
491
+ proxy_uri.port,
492
+ proxy_uri.user,
493
+ proxy_uri.password,
494
+ )
363
495
  end
364
496
 
365
497
  http_object.use_ssl = (our_uri.scheme == "https")
@@ -377,7 +509,7 @@ module OAuth
377
509
  http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
378
510
  http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
379
511
  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]
512
+ http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
381
513
  http_object.set_debug_output(debug_output) if debug_output
382
514
 
383
515
  http_object
@@ -392,7 +524,7 @@ module OAuth
392
524
  # if the base site contains a path, add it now
393
525
  # only add if the site host matches the current http object's host
394
526
  # (in case we've specified a full url for token requests)
395
- uri = URI.parse(site)
527
+ uri = URI.parse(site)
396
528
  path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
397
529
 
398
530
  headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
@@ -440,7 +572,7 @@ module OAuth
440
572
  end
441
573
 
442
574
  def marshal_dump(*_args)
443
- { key: @key, secret: @secret, options: @options }
575
+ {key: @key, secret: @secret, options: @options}
444
576
  end
445
577
 
446
578
  def marshal_load(data)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OAuth
2
4
  class Error < StandardError
3
5
  end
@@ -1,10 +1,13 @@
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
7
- @params = params
10
+ @params = params
8
11
  end
9
12
 
10
13
  def to_s
@@ -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"