oauth 0.5.6 → 1.1.7

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 (72) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +915 -0
  4. data/CITATION.cff +20 -0
  5. data/CODE_OF_CONDUCT.md +134 -0
  6. data/CONTRIBUTING.md +272 -0
  7. data/FUNDING.md +74 -0
  8. data/LICENSE.md +71 -0
  9. data/README.md +718 -0
  10. data/RUBOCOP.md +71 -0
  11. data/SECURITY.md +21 -0
  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 +33 -22
  15. data/lib/oauth/client/em_http.rb +110 -103
  16. data/lib/oauth/client/helper.rb +87 -82
  17. data/lib/oauth/client/net_http.rb +140 -107
  18. data/lib/oauth/client.rb +2 -0
  19. data/lib/oauth/consumer.rb +282 -149
  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 +7 -1
  23. data/lib/oauth/errors.rb +5 -3
  24. data/lib/oauth/helper.rb +48 -18
  25. data/lib/oauth/oauth.rb +31 -7
  26. data/lib/oauth/oauth_test_helper.rb +6 -4
  27. data/lib/oauth/optional.rb +20 -0
  28. data/lib/oauth/request_proxy/action_controller_request.rb +53 -71
  29. data/lib/oauth/request_proxy/action_dispatch_request.rb +42 -4
  30. data/lib/oauth/request_proxy/base.rb +146 -131
  31. data/lib/oauth/request_proxy/curb_request.rb +49 -43
  32. data/lib/oauth/request_proxy/em_http_request.rb +60 -49
  33. data/lib/oauth/request_proxy/jabber_request.rb +19 -9
  34. data/lib/oauth/request_proxy/mock_request.rb +5 -3
  35. data/lib/oauth/request_proxy/net_http.rb +61 -54
  36. data/lib/oauth/request_proxy/rack_request.rb +31 -31
  37. data/lib/oauth/request_proxy/rest_client_request.rb +55 -50
  38. data/lib/oauth/request_proxy/typhoeus_request.rb +51 -45
  39. data/lib/oauth/request_proxy.rb +21 -14
  40. data/lib/oauth/server.rb +18 -12
  41. data/lib/oauth/signature/base.rb +88 -71
  42. data/lib/oauth/signature/hmac/sha1.rb +16 -10
  43. data/lib/oauth/signature/hmac/sha256.rb +16 -10
  44. data/lib/oauth/signature/plaintext.rb +18 -20
  45. data/lib/oauth/signature/rsa/sha1.rb +71 -38
  46. data/lib/oauth/signature.rb +41 -34
  47. data/lib/oauth/token.rb +7 -5
  48. data/lib/oauth/tokens/access_token.rb +6 -4
  49. data/lib/oauth/tokens/consumer_token.rb +11 -7
  50. data/lib/oauth/tokens/request_token.rb +17 -10
  51. data/lib/oauth/tokens/server_token.rb +2 -1
  52. data/lib/oauth/tokens/token.rb +15 -1
  53. data/lib/oauth/version.rb +6 -1
  54. data/lib/oauth.rb +19 -9
  55. data/sig/oauth/consumer.rbs +9 -0
  56. data/sig/oauth/signature/base.rbs +12 -0
  57. data/sig/oauth/tokens/token.rbs +8 -0
  58. data/sig/oauth/version.rbs +6 -0
  59. data.tar.gz.sig +2 -0
  60. metadata +313 -84
  61. metadata.gz.sig +3 -0
  62. data/LICENSE +0 -20
  63. data/README.rdoc +0 -88
  64. data/TODO +0 -32
  65. data/bin/oauth +0 -11
  66. data/lib/oauth/cli/authorize_command.rb +0 -71
  67. data/lib/oauth/cli/base_command.rb +0 -208
  68. data/lib/oauth/cli/help_command.rb +0 -22
  69. data/lib/oauth/cli/query_command.rb +0 -25
  70. data/lib/oauth/cli/sign_command.rb +0 -81
  71. data/lib/oauth/cli/version_command.rb +0 -7
  72. data/lib/oauth/cli.rb +0 -56
@@ -1,23 +1,44 @@
1
- require 'net/http'
2
- require 'net/https'
3
- require 'oauth/oauth'
4
- require 'oauth/client/net_http'
5
- require 'oauth/errors'
6
- require 'cgi'
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "net/https"
5
+ require "oauth/oauth"
6
+ require "oauth/client/net_http"
7
+ require "oauth/errors"
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
- if ENV['SSL_CERT_FILE']
12
- if File.exist?(ENV['SSL_CERT_FILE'])
13
- CA_FILE = ENV['SSL_CERT_FILE']
28
+ if ENV["SSL_CERT_FILE"]
29
+ if File.exist?(ENV["SSL_CERT_FILE"])
30
+ CA_FILE = ENV["SSL_CERT_FILE"]
14
31
  else
15
32
  raise "The SSL CERT provided does not exist."
16
33
  end
17
34
  end
18
35
 
19
- if !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)
36
+ unless defined?(CA_FILE)
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
- # http://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,14 +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.inject({}) do |opts, (key, value)|
98
- opts[key.to_sym] = value
99
- opts
100
- end)
133
+ snaky_options = SnakyHash::SymbolKeyed.new(options)
134
+ @options = @@default_options.merge(snaky_options)
101
135
  end
102
136
 
103
137
  # The default http method
@@ -106,14 +140,12 @@ module OAuth
106
140
  end
107
141
 
108
142
  def debug_output
109
- @debug_output ||= begin
110
- case @options[:debug_output]
111
- when nil, false
112
- when true
113
- $stdout
114
- else
115
- @options[:debug_output]
116
- end
143
+ @debug_output ||= case @options[:debug_output]
144
+ when nil, false
145
+ when true
146
+ $stdout
147
+ else
148
+ @options[:debug_output]
117
149
  end
118
150
  end
119
151
 
@@ -125,45 +157,92 @@ module OAuth
125
157
  # Contains the root URI for this site
126
158
  def uri(custom_uri = nil)
127
159
  if custom_uri
128
- @uri = custom_uri
160
+ @uri = custom_uri
129
161
  @http = create_http # yike, oh well. less intrusive this way
130
- else # if no custom passed, we use existing, which, if unset, is set to site uri
162
+ else # if no custom passed, we use existing, which, if unset, is set to site uri
131
163
  @uri ||= URI.parse(site)
132
164
  end
133
165
  end
134
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]
135
182
  def get_access_token(request_token, request_options = {}, *arguments, &block)
136
- 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
+ )
137
191
  OAuth::AccessToken.from_hash(self, response)
138
192
  end
139
193
 
140
194
  # Makes a request to the service for a new OAuth::RequestToken
141
195
  #
142
- # @request_token = @consumer.get_request_token
196
+ # Example:
197
+ # @request_token = @consumer.get_request_token
143
198
  #
144
199
  # To include OAuth parameters:
145
- #
146
- # @request_token = @consumer.get_request_token \
147
- # :oauth_callback => "http://example.com/cb"
200
+ # @request_token = @consumer.get_request_token(
201
+ # oauth_callback: "http://example.com/cb"
202
+ # )
148
203
  #
149
204
  # To include application-specific parameters:
205
+ # @request_token = @consumer.get_request_token({}, foo: "bar")
150
206
  #
151
- # @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.
152
215
  #
153
- # 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]
154
224
  def get_request_token(request_options = {}, *arguments, &block)
155
225
  # if oauth_callback wasn't provided, it is assumed that oauth_verifiers
156
226
  # will be exchanged out of band
157
227
  request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
158
228
 
159
- if block_given?
160
- response = token_request(http_method,
161
- (request_token_url? ? request_token_url : request_token_path),
162
- nil,
163
- request_options,
164
- *arguments, &block)
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
+ )
165
238
  else
166
- response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
239
+ token_request(
240
+ http_method,
241
+ (request_token_url? ? request_token_url : request_token_path),
242
+ nil,
243
+ request_options,
244
+ *arguments,
245
+ )
167
246
  end
168
247
  OAuth::RequestToken.from_hash(self, response)
169
248
  end
@@ -179,26 +258,27 @@ module OAuth
179
258
  # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
180
259
  #
181
260
  def request(http_method, path, token = nil, request_options = {}, *arguments)
182
- if path !~ /^\//
261
+ unless %r{^/} =~ path
183
262
  @http = create_http(path)
184
- _uri = URI.parse(path)
185
- path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
263
+ uri = URI.parse(path)
264
+ path = "#{uri.path}#{"?#{uri.query}" if uri.query}"
186
265
  end
187
266
 
188
267
  # override the request with your own, this is useful for file uploads which Net::HTTP does not do
189
268
  req = create_signed_request(http_method, path, token, request_options, *arguments)
190
- return nil if block_given? and yield(req) == :done
269
+ return if block_given? && (yield(req) == :done)
270
+
191
271
  rsp = http.request(req)
192
272
  # check for an error reported by the Problem Reporting extension
193
- # (http://wiki.oauth.net/ProblemReporting)
273
+ # (https://wiki.oauth.net/ProblemReporting)
194
274
  # note: a 200 may actually be an error; check for an oauth_problem key to be sure
195
275
  if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
196
- (h = headers.select { |hdr| hdr =~ /^OAuth / }).any? &&
197
- h.first =~ /oauth_problem/
276
+ (h = headers.grep(/^OAuth /)).any? &&
277
+ h.first.include?("oauth_problem")
198
278
 
199
279
  # puts "Header: #{h.first}"
200
280
 
201
- # TODO doesn't handle broken responses from api.login.yahoo.com
281
+ # TODO: doesn't handle broken responses from api.login.yahoo.com
202
282
  # remove debug code when done
203
283
  params = OAuth::Helper.parse_header(h.first)
204
284
 
@@ -220,36 +300,34 @@ module OAuth
220
300
  end
221
301
 
222
302
  # Creates a request and parses the result as url_encoded. This is used internally for the RequestToken and AccessToken requests.
223
- def token_request(http_method, path, token = nil, request_options = {}, *arguments)
224
- request_options[:token_request] ||= true
225
- 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)
226
305
  case response.code.to_i
227
306
 
228
307
  when (200..299)
229
- if block_given?
230
- yield response.body
308
+ if block
309
+ block.call(response.body)
231
310
  else
232
311
  # symbolize keys
233
312
  # TODO this could be considered unexpected behavior; symbols or not?
234
313
  # TODO this also drops subsequent values from multi-valued keys
235
- CGI.parse(response.body).inject({}) do |h,(k,v)|
314
+ CGI.parse(response.body).each_with_object({}) do |(k, v), h|
236
315
  h[k.strip.to_sym] = v.first
237
- h[k.strip] = v.first
238
- h
316
+ h[k.strip] = v.first
239
317
  end
240
318
  end
241
319
  when (300..399)
242
- # this is a redirect
243
- uri = URI.parse(response['location'])
244
- our_uri = URI.parse(site)
320
+ current_uri = token_request_uri(path)
321
+ redirected_uri = token_request_redirect_uri(current_uri, response)
322
+ response.error! unless redirected_uri
245
323
 
246
- if uri.path == path && our_uri.host != uri.host
247
- options[:site] = "#{uri.scheme}://#{uri.host}"
248
- @http = create_http
249
- 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)
250
328
 
251
- response.error! if uri.path == path && our_uri.host == uri.host # careful of those infinite redirects
252
- self.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)
253
331
  when (400..499)
254
332
  raise OAuth::Unauthorized, response
255
333
  else
@@ -257,6 +335,55 @@ module OAuth
257
335
  end
258
336
  end
259
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
+
260
387
  # Sign the Request object. Use this if you have an externally generated http request object you want to sign.
261
388
  def sign!(request, token = nil, request_options = {})
262
389
  request.oauth!(http, self, token, options.merge(request_options))
@@ -272,7 +399,8 @@ module OAuth
272
399
  end
273
400
 
274
401
  def request_endpoint
275
- return nil if @options[:request_endpoint].nil?
402
+ return if @options[:request_endpoint].nil?
403
+
276
404
  @options[:request_endpoint].to_s
277
405
  end
278
406
 
@@ -296,37 +424,37 @@ module OAuth
296
424
  @options[:access_token_path]
297
425
  end
298
426
 
299
- # TODO this is ugly, rewrite
427
+ # TODO: this is ugly, rewrite
300
428
  def request_token_url
301
- @options[:request_token_url] || site + request_token_path
429
+ @options[:request_token_url] || (site + request_token_path)
302
430
  end
303
431
 
304
432
  def request_token_url?
305
- @options.has_key?(:request_token_url)
433
+ @options.key?(:request_token_url)
306
434
  end
307
435
 
308
436
  def authenticate_url
309
- @options[:authenticate_url] || site + authenticate_path
437
+ @options[:authenticate_url] || (site + authenticate_path)
310
438
  end
311
439
 
312
440
  def authenticate_url?
313
- @options.has_key?(:authenticate_url)
441
+ @options.key?(:authenticate_url)
314
442
  end
315
443
 
316
444
  def authorize_url
317
- @options[:authorize_url] || site + authorize_path
445
+ @options[:authorize_url] || (site + authorize_path)
318
446
  end
319
447
 
320
448
  def authorize_url?
321
- @options.has_key?(:authorize_url)
449
+ @options.key?(:authorize_url)
322
450
  end
323
451
 
324
452
  def access_token_url
325
- @options[:access_token_url] || site + access_token_path
453
+ @options[:access_token_url] || (site + access_token_path)
326
454
  end
327
455
 
328
456
  def access_token_url?
329
- @options.has_key?(:access_token_url)
457
+ @options.key?(:access_token_url)
330
458
  end
331
459
 
332
460
  def proxy
@@ -336,37 +464,43 @@ module OAuth
336
464
  protected
337
465
 
338
466
  # Instantiates the http object
339
- def create_http(_url = nil)
340
-
341
-
342
- if !request_endpoint.nil?
343
- _url = request_endpoint
344
- end
345
-
467
+ def create_http(url = nil)
468
+ url = request_endpoint unless request_endpoint.nil?
346
469
 
347
- if _url.nil? || _url[0] =~ /^\//
348
- our_uri = URI.parse(site)
470
+ our_uri = if url.nil? || url[0] =~ %r{^/}
471
+ URI.parse(site)
349
472
  else
350
- our_uri = URI.parse(_url)
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
351
481
  end
352
482
 
353
-
354
483
  if proxy.nil?
355
484
  http_object = Net::HTTP.new(our_uri.host, our_uri.port)
356
485
  else
357
486
  proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
358
- 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
+ )
359
495
  end
360
496
 
361
- http_object.use_ssl = (our_uri.scheme == 'https')
497
+ http_object.use_ssl = (our_uri.scheme == "https")
362
498
 
363
499
  if @options[:no_verify]
364
500
  http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
365
501
  else
366
- ca_file = @options[:ca_file] || CA_FILE
367
- if ca_file
368
- http_object.ca_file = ca_file
369
- end
502
+ ca_file = @options[:ca_file] || CA_FILE
503
+ http_object.ca_file = ca_file if ca_file
370
504
  http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
371
505
  http_object.verify_depth = 5
372
506
  end
@@ -374,6 +508,8 @@ module OAuth
374
508
  http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 60
375
509
  http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
376
510
  http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
511
+ http_object.cert = @options[:ssl_client_cert] if @options[:ssl_client_cert]
512
+ http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
377
513
  http_object.set_debug_output(debug_output) if debug_output
378
514
 
379
515
  http_object
@@ -383,41 +519,39 @@ module OAuth
383
519
  def create_http_request(http_method, path, *arguments)
384
520
  http_method = http_method.to_sym
385
521
 
386
- if [:post, :put, :patch].include?(http_method)
387
- data = arguments.shift
388
- end
522
+ data = arguments.shift if %i[post put patch].include?(http_method)
389
523
 
390
524
  # if the base site contains a path, add it now
391
525
  # only add if the site host matches the current http object's host
392
526
  # (in case we've specified a full url for token requests)
393
- uri = URI.parse(site)
394
- path = uri.path + path if uri.path && uri.path != '/' && uri.host == http.address
527
+ uri = URI.parse(site)
528
+ path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
395
529
 
396
530
  headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
397
531
 
398
532
  case http_method
399
533
  when :post
400
- request = Net::HTTP::Post.new(path,headers)
401
- request["Content-Length"] = '0' # Default to 0
534
+ request = Net::HTTP::Post.new(path, headers)
535
+ request["Content-Length"] = "0" # Default to 0
402
536
  when :put
403
- request = Net::HTTP::Put.new(path,headers)
404
- request["Content-Length"] = '0' # Default to 0
537
+ request = Net::HTTP::Put.new(path, headers)
538
+ request["Content-Length"] = "0" # Default to 0
405
539
  when :patch
406
- request = Net::HTTP::Patch.new(path,headers)
407
- request["Content-Length"] = '0' # Default to 0
540
+ request = Net::HTTP::Patch.new(path, headers)
541
+ request["Content-Length"] = "0" # Default to 0
408
542
  when :get
409
- request = Net::HTTP::Get.new(path,headers)
543
+ request = Net::HTTP::Get.new(path, headers)
410
544
  when :delete
411
- request = Net::HTTP::Delete.new(path,headers)
545
+ request = Net::HTTP::Delete.new(path, headers)
412
546
  when :head
413
- request = Net::HTTP::Head.new(path,headers)
547
+ request = Net::HTTP::Head.new(path, headers)
414
548
  else
415
- raise ArgumentError, "Don't know how to handle http_method: :#{http_method.to_s}"
549
+ raise ArgumentError, "Don't know how to handle http_method: :#{http_method}"
416
550
  end
417
551
 
418
552
  if data.is_a?(Hash)
419
553
  request.body = OAuth::Helper.normalize(data)
420
- request.content_type = 'application/x-www-form-urlencoded'
554
+ request.content_type = "application/x-www-form-urlencoded"
421
555
  elsif data
422
556
  if data.respond_to?(:read)
423
557
  request.body_stream = data
@@ -437,13 +571,12 @@ module OAuth
437
571
  request
438
572
  end
439
573
 
440
- def marshal_dump(*args)
441
- {:key => @key, :secret => @secret, :options => @options}
574
+ def marshal_dump(*_args)
575
+ {key: @key, secret: @secret, options: @options}
442
576
  end
443
577
 
444
578
  def marshal_load(data)
445
579
  initialize(data[:key], data[:secret], data[:options])
446
580
  end
447
-
448
581
  end
449
582
  end
@@ -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