oauth 0.5.8 → 1.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +136 -115
- data/CODE_OF_CONDUCT.md +0 -0
- data/CONTRIBUTING.md +19 -2
- data/LICENSE +2 -1
- data/README.md +267 -67
- data/SECURITY.md +18 -8
- data/TODO +0 -0
- data/lib/oauth/client/action_controller_request.rb +17 -15
- data/lib/oauth/client/em_http.rb +30 -30
- data/lib/oauth/client/helper.rb +76 -75
- data/lib/oauth/client/net_http.rb +109 -102
- data/lib/oauth/client.rb +2 -0
- data/lib/oauth/consumer.rb +113 -110
- data/lib/oauth/errors/error.rb +2 -0
- data/lib/oauth/errors/problem.rb +3 -0
- data/lib/oauth/errors/unauthorized.rb +4 -0
- data/lib/oauth/errors.rb +2 -0
- data/lib/oauth/helper.rb +16 -12
- data/lib/oauth/oauth.rb +6 -4
- data/lib/oauth/oauth_test_helper.rb +2 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +3 -24
- data/lib/oauth/request_proxy/action_dispatch_request.rb +0 -0
- data/lib/oauth/request_proxy/base.rb +2 -2
- data/lib/oauth/request_proxy/curb_request.rb +0 -0
- data/lib/oauth/request_proxy/em_http_request.rb +0 -0
- data/lib/oauth/request_proxy/jabber_request.rb +0 -0
- data/lib/oauth/request_proxy/mock_request.rb +1 -1
- data/lib/oauth/request_proxy/net_http.rb +5 -7
- data/lib/oauth/request_proxy/rack_request.rb +0 -0
- data/lib/oauth/request_proxy/rest_client_request.rb +2 -1
- data/lib/oauth/request_proxy/typhoeus_request.rb +0 -0
- data/lib/oauth/request_proxy.rb +7 -4
- data/lib/oauth/server.rb +12 -10
- data/lib/oauth/signature/base.rb +71 -66
- data/lib/oauth/signature/hmac/sha1.rb +15 -9
- data/lib/oauth/signature/hmac/sha256.rb +15 -9
- data/lib/oauth/signature/plaintext.rb +18 -20
- data/lib/oauth/signature/rsa/sha1.rb +46 -38
- data/lib/oauth/signature.rb +8 -5
- data/lib/oauth/token.rb +2 -0
- data/lib/oauth/tokens/access_token.rb +2 -0
- data/lib/oauth/tokens/consumer_token.rb +4 -2
- data/lib/oauth/tokens/request_token.rb +12 -10
- data/lib/oauth/tokens/server_token.rb +2 -1
- data/lib/oauth/tokens/token.rb +2 -0
- data/lib/oauth/version.rb +5 -1
- data/lib/oauth.rb +9 -2
- metadata +87 -35
- data/bin/oauth +0 -11
- data/lib/oauth/cli/authorize_command.rb +0 -71
- data/lib/oauth/cli/base_command.rb +0 -208
- data/lib/oauth/cli/help_command.rb +0 -22
- data/lib/oauth/cli/query_command.rb +0 -25
- data/lib/oauth/cli/sign_command.rb +0 -81
- data/lib/oauth/cli/version_command.rb +0 -7
- data/lib/oauth/cli.rb +0 -56
data/lib/oauth/consumer.rb
CHANGED
@@ -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"
|
@@ -16,8 +18,9 @@ module OAuth
|
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
CA_FILES = %
|
21
|
+
unless defined?(CA_FILE)
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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,10 +105,8 @@ module OAuth
|
|
94
105
|
@secret = consumer_secret
|
95
106
|
|
96
107
|
# ensure that keys are symbols
|
97
|
-
|
98
|
-
|
99
|
-
opts
|
100
|
-
end)
|
108
|
+
snaky_options = SnakyHash::SymbolKeyed.new(options)
|
109
|
+
@options = @@default_options.merge(snaky_options)
|
101
110
|
end
|
102
111
|
|
103
112
|
# The default http method
|
@@ -106,15 +115,13 @@ module OAuth
|
|
106
115
|
end
|
107
116
|
|
108
117
|
def debug_output
|
109
|
-
@debug_output ||=
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
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
|
118
125
|
end
|
119
126
|
|
120
127
|
# The HTTP object for the site. The HTTP Object is what you get when you do Net::HTTP.new
|
@@ -127,13 +134,14 @@ module OAuth
|
|
127
134
|
if custom_uri
|
128
135
|
@uri = custom_uri
|
129
136
|
@http = create_http # yike, oh well. less intrusive this way
|
130
|
-
else
|
137
|
+
else # if no custom passed, we use existing, which, if unset, is set to site uri
|
131
138
|
@uri ||= URI.parse(site)
|
132
139
|
end
|
133
140
|
end
|
134
141
|
|
135
142
|
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,
|
143
|
+
response = token_request(http_method, (access_token_url? ? access_token_url : access_token_path), request_token,
|
144
|
+
request_options, *arguments, &block)
|
137
145
|
OAuth::AccessToken.from_hash(self, response)
|
138
146
|
end
|
139
147
|
|
@@ -156,18 +164,19 @@ module OAuth
|
|
156
164
|
# will be exchanged out of band
|
157
165
|
request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
|
158
166
|
|
159
|
-
if
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
167
|
+
response = if block
|
168
|
+
token_request(
|
169
|
+
http_method,
|
170
|
+
(request_token_url? ? request_token_url : request_token_path),
|
171
|
+
nil,
|
172
|
+
request_options,
|
173
|
+
*arguments,
|
174
|
+
&block
|
175
|
+
)
|
176
|
+
else
|
177
|
+
token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil,
|
178
|
+
request_options, *arguments)
|
179
|
+
end
|
171
180
|
OAuth::RequestToken.from_hash(self, response)
|
172
181
|
end
|
173
182
|
|
@@ -182,7 +191,7 @@ module OAuth
|
|
182
191
|
# @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
|
183
192
|
#
|
184
193
|
def request(http_method, path, token = nil, request_options = {}, *arguments)
|
185
|
-
|
194
|
+
unless %r{^/}.match?(path)
|
186
195
|
@http = create_http(path)
|
187
196
|
_uri = URI.parse(path)
|
188
197
|
path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
|
@@ -190,18 +199,19 @@ module OAuth
|
|
190
199
|
|
191
200
|
# override the request with your own, this is useful for file uploads which Net::HTTP does not do
|
192
201
|
req = create_signed_request(http_method, path, token, request_options, *arguments)
|
193
|
-
return nil if block_given?
|
202
|
+
return nil if block_given? && (yield(req) == :done)
|
203
|
+
|
194
204
|
rsp = http.request(req)
|
195
205
|
# check for an error reported by the Problem Reporting extension
|
196
206
|
# (https://wiki.oauth.net/ProblemReporting)
|
197
207
|
# note: a 200 may actually be an error; check for an oauth_problem key to be sure
|
198
208
|
if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
|
199
|
-
|
200
|
-
|
209
|
+
(h = headers.grep(/^OAuth /)).any? &&
|
210
|
+
h.first.include?("oauth_problem")
|
201
211
|
|
202
212
|
# puts "Header: #{h.first}"
|
203
213
|
|
204
|
-
# TODO doesn't handle broken responses from api.login.yahoo.com
|
214
|
+
# TODO: doesn't handle broken responses from api.login.yahoo.com
|
205
215
|
# remove debug code when done
|
206
216
|
params = OAuth::Helper.parse_header(h.first)
|
207
217
|
|
@@ -235,10 +245,9 @@ module OAuth
|
|
235
245
|
# symbolize keys
|
236
246
|
# TODO this could be considered unexpected behavior; symbols or not?
|
237
247
|
# TODO this also drops subsequent values from multi-valued keys
|
238
|
-
CGI.parse(response.body).
|
248
|
+
CGI.parse(response.body).each_with_object({}) do |(k, v), h|
|
239
249
|
h[k.strip.to_sym] = v.first
|
240
250
|
h[k.strip] = v.first
|
241
|
-
h
|
242
251
|
end
|
243
252
|
end
|
244
253
|
when (300..399)
|
@@ -250,11 +259,11 @@ module OAuth
|
|
250
259
|
response.error! if uri.path == path && our_uri.host == uri.host
|
251
260
|
|
252
261
|
if uri.path == path && our_uri.host != uri.host
|
253
|
-
|
254
|
-
|
262
|
+
options[:site] = "#{uri.scheme}://#{uri.host}"
|
263
|
+
@http = create_http
|
255
264
|
end
|
256
265
|
|
257
|
-
|
266
|
+
token_request(http_method, uri.path, token, request_options, arguments)
|
258
267
|
when (400..499)
|
259
268
|
raise OAuth::Unauthorized, response
|
260
269
|
else
|
@@ -278,6 +287,7 @@ module OAuth
|
|
278
287
|
|
279
288
|
def request_endpoint
|
280
289
|
return nil if @options[:request_endpoint].nil?
|
290
|
+
|
281
291
|
@options[:request_endpoint].to_s
|
282
292
|
end
|
283
293
|
|
@@ -301,37 +311,37 @@ module OAuth
|
|
301
311
|
@options[:access_token_path]
|
302
312
|
end
|
303
313
|
|
304
|
-
# TODO this is ugly, rewrite
|
314
|
+
# TODO: this is ugly, rewrite
|
305
315
|
def request_token_url
|
306
|
-
@options[:request_token_url] || site + request_token_path
|
316
|
+
@options[:request_token_url] || (site + request_token_path)
|
307
317
|
end
|
308
318
|
|
309
319
|
def request_token_url?
|
310
|
-
@options.
|
320
|
+
@options.key?(:request_token_url)
|
311
321
|
end
|
312
322
|
|
313
323
|
def authenticate_url
|
314
|
-
@options[:authenticate_url] || site + authenticate_path
|
324
|
+
@options[:authenticate_url] || (site + authenticate_path)
|
315
325
|
end
|
316
326
|
|
317
327
|
def authenticate_url?
|
318
|
-
@options.
|
328
|
+
@options.key?(:authenticate_url)
|
319
329
|
end
|
320
330
|
|
321
331
|
def authorize_url
|
322
|
-
@options[:authorize_url] || site + authorize_path
|
332
|
+
@options[:authorize_url] || (site + authorize_path)
|
323
333
|
end
|
324
334
|
|
325
335
|
def authorize_url?
|
326
|
-
@options.
|
336
|
+
@options.key?(:authorize_url)
|
327
337
|
end
|
328
338
|
|
329
339
|
def access_token_url
|
330
|
-
@options[:access_token_url] || site + access_token_path
|
340
|
+
@options[:access_token_url] || (site + access_token_path)
|
331
341
|
end
|
332
342
|
|
333
343
|
def access_token_url?
|
334
|
-
@options.
|
344
|
+
@options.key?(:access_token_url)
|
335
345
|
end
|
336
346
|
|
337
347
|
def proxy
|
@@ -342,12 +352,9 @@ module OAuth
|
|
342
352
|
|
343
353
|
# Instantiates the http object
|
344
354
|
def create_http(_url = nil)
|
355
|
+
_url = request_endpoint unless request_endpoint.nil?
|
345
356
|
|
346
|
-
if
|
347
|
-
_url = request_endpoint
|
348
|
-
end
|
349
|
-
|
350
|
-
our_uri = if _url.nil? || _url[0] =~ /^\//
|
357
|
+
our_uri = if _url.nil? || _url[0] =~ %r{^/}
|
351
358
|
URI.parse(site)
|
352
359
|
else
|
353
360
|
your_uri = URI.parse(_url)
|
@@ -364,7 +371,8 @@ module OAuth
|
|
364
371
|
http_object = Net::HTTP.new(our_uri.host, our_uri.port)
|
365
372
|
else
|
366
373
|
proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
|
367
|
-
http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user,
|
374
|
+
http_object = Net::HTTP.new(our_uri.host, our_uri.port, proxy_uri.host, proxy_uri.port, proxy_uri.user,
|
375
|
+
proxy_uri.password)
|
368
376
|
end
|
369
377
|
|
370
378
|
http_object.use_ssl = (our_uri.scheme == "https")
|
@@ -372,10 +380,8 @@ module OAuth
|
|
372
380
|
if @options[:no_verify]
|
373
381
|
http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
374
382
|
else
|
375
|
-
ca_file =
|
376
|
-
if ca_file
|
377
|
-
http_object.ca_file = ca_file
|
378
|
-
end
|
383
|
+
ca_file = @options[:ca_file] || CA_FILE
|
384
|
+
http_object.ca_file = ca_file if ca_file
|
379
385
|
http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
380
386
|
http_object.verify_depth = 5
|
381
387
|
end
|
@@ -384,7 +390,7 @@ module OAuth
|
|
384
390
|
http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
|
385
391
|
http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
|
386
392
|
http_object.cert = @options[:ssl_client_cert] if @options[:ssl_client_cert]
|
387
|
-
http_object.key
|
393
|
+
http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
|
388
394
|
http_object.set_debug_output(debug_output) if debug_output
|
389
395
|
|
390
396
|
http_object
|
@@ -394,36 +400,34 @@ module OAuth
|
|
394
400
|
def create_http_request(http_method, path, *arguments)
|
395
401
|
http_method = http_method.to_sym
|
396
402
|
|
397
|
-
if [
|
398
|
-
data = arguments.shift
|
399
|
-
end
|
403
|
+
data = arguments.shift if %i[post put patch].include?(http_method)
|
400
404
|
|
401
405
|
# if the base site contains a path, add it now
|
402
406
|
# only add if the site host matches the current http object's host
|
403
407
|
# (in case we've specified a full url for token requests)
|
404
|
-
uri
|
408
|
+
uri = URI.parse(site)
|
405
409
|
path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
|
406
410
|
|
407
411
|
headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
|
408
412
|
|
409
413
|
case http_method
|
410
414
|
when :post
|
411
|
-
request = Net::HTTP::Post.new(path,headers)
|
415
|
+
request = Net::HTTP::Post.new(path, headers)
|
412
416
|
request["Content-Length"] = "0" # Default to 0
|
413
417
|
when :put
|
414
|
-
request = Net::HTTP::Put.new(path,headers)
|
418
|
+
request = Net::HTTP::Put.new(path, headers)
|
415
419
|
request["Content-Length"] = "0" # Default to 0
|
416
420
|
when :patch
|
417
|
-
request = Net::HTTP::Patch.new(path,headers)
|
421
|
+
request = Net::HTTP::Patch.new(path, headers)
|
418
422
|
request["Content-Length"] = "0" # Default to 0
|
419
423
|
when :get
|
420
|
-
request = Net::HTTP::Get.new(path,headers)
|
424
|
+
request = Net::HTTP::Get.new(path, headers)
|
421
425
|
when :delete
|
422
|
-
request =
|
426
|
+
request = Net::HTTP::Delete.new(path, headers)
|
423
427
|
when :head
|
424
|
-
request = Net::HTTP::Head.new(path,headers)
|
428
|
+
request = Net::HTTP::Head.new(path, headers)
|
425
429
|
else
|
426
|
-
raise ArgumentError, "Don't know how to handle http_method: :#{http_method
|
430
|
+
raise ArgumentError, "Don't know how to handle http_method: :#{http_method}"
|
427
431
|
end
|
428
432
|
|
429
433
|
if data.is_a?(Hash)
|
@@ -448,13 +452,12 @@ module OAuth
|
|
448
452
|
request
|
449
453
|
end
|
450
454
|
|
451
|
-
def marshal_dump(*
|
452
|
-
{:
|
455
|
+
def marshal_dump(*_args)
|
456
|
+
{ key: @key, secret: @secret, options: @options }
|
453
457
|
end
|
454
458
|
|
455
459
|
def marshal_load(data)
|
456
460
|
initialize(data[:key], data[:secret], data[:options])
|
457
461
|
end
|
458
|
-
|
459
462
|
end
|
460
463
|
end
|
data/lib/oauth/errors/error.rb
CHANGED
data/lib/oauth/errors/problem.rb
CHANGED
data/lib/oauth/errors.rb
CHANGED
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
|
-
|
9
|
+
module_function
|
7
10
|
|
8
11
|
# Escape +value+ by URL encoding all non-reserved character.
|
9
12
|
#
|
@@ -24,13 +27,13 @@ module OAuth
|
|
24
27
|
|
25
28
|
# Generate a random key of up to +size+ bytes. The value returned is Base64 encoded with non-word
|
26
29
|
# characters removed.
|
27
|
-
def generate_key(size=32)
|
30
|
+
def generate_key(size = 32)
|
28
31
|
Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, "")
|
29
32
|
end
|
30
33
|
|
31
|
-
|
34
|
+
alias generate_nonce generate_key
|
32
35
|
|
33
|
-
def generate_timestamp
|
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
|
-
|
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
|
@@ -51,13 +55,13 @@ module OAuth
|
|
51
55
|
normalize_nested_query(values, k)
|
52
56
|
else
|
53
57
|
values.sort.collect do |v|
|
54
|
-
[escape(k),escape(v)]
|
58
|
+
[escape(k), escape(v)].join("=")
|
55
59
|
end
|
56
60
|
end
|
57
|
-
|
61
|
+
when Hash
|
58
62
|
normalize_nested_query(values, k)
|
59
63
|
else
|
60
|
-
[escape(k),escape(values)]
|
64
|
+
[escape(k), escape(values)].join("=")
|
61
65
|
end
|
62
66
|
end * "&"
|
63
67
|
end
|
@@ -76,7 +80,7 @@ module OAuth
|
|
76
80
|
normalize_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
|
77
81
|
end.flatten.sort
|
78
82
|
else
|
79
|
-
[escape(prefix), escape(value)]
|
83
|
+
[escape(prefix), escape(value)].join("=")
|
80
84
|
end
|
81
85
|
end
|
82
86
|
|
@@ -90,16 +94,16 @@ module OAuth
|
|
90
94
|
#
|
91
95
|
def parse_header(header)
|
92
96
|
# decompose
|
93
|
-
params = header[6,header.length].split(/[,=&]/)
|
97
|
+
params = header[6, header.length].split(/[,=&]/)
|
94
98
|
|
95
99
|
# odd number of arguments - must be a malformed header.
|
96
|
-
raise OAuth::Problem
|
100
|
+
raise OAuth::Problem, "Invalid authorization header" if params.size.odd?
|
97
101
|
|
98
102
|
params.map! do |v|
|
99
103
|
# strip and unescape
|
100
104
|
val = unescape(v.strip)
|
101
105
|
# strip quotes
|
102
|
-
val.sub(
|
106
|
+
val.sub(/^"(.*)"$/, '\1')
|
103
107
|
end
|
104
108
|
|
105
109
|
# convert into a Hash
|
data/lib/oauth/oauth.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
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
6
|
OUT_OF_BAND = "oob"
|
5
7
|
|
6
8
|
# required parameters, per sections 6.1.1, 6.3.1, and 7
|
7
|
-
PARAMETERS = %w
|
8
|
-
|
9
|
-
|
9
|
+
PARAMETERS = %w[oauth_callback oauth_consumer_key oauth_token
|
10
|
+
oauth_signature_method oauth_timestamp oauth_nonce oauth_verifier
|
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,36 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support"
|
4
|
-
require "active_support/version"
|
5
4
|
require "action_controller"
|
6
5
|
require "uri"
|
7
6
|
|
8
|
-
|
9
|
-
# rails 2.x
|
10
|
-
require "action_controller/request"
|
11
|
-
unless ActionController::Request::HTTP_METHODS.include?("patch")
|
12
|
-
ActionController::Request::HTTP_METHODS << "patch"
|
13
|
-
ActionController::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
|
14
|
-
ActionController::Request::HTTP_METHOD_LOOKUP["patch"] = :patch
|
15
|
-
end
|
16
|
-
|
17
|
-
elsif Gem::Version.new(ActiveSupport::VERSION::STRING) < Gem::Version.new("4")
|
18
|
-
# rails 3.x
|
19
|
-
require "action_dispatch/http/request"
|
20
|
-
unless ActionDispatch::Request::HTTP_METHODS.include?("patch")
|
21
|
-
ActionDispatch::Request::HTTP_METHODS << "patch"
|
22
|
-
ActionDispatch::Request::HTTP_METHOD_LOOKUP["PATCH"] = :patch
|
23
|
-
ActionDispatch::Request::HTTP_METHOD_LOOKUP["patch"] = :patch
|
24
|
-
end
|
25
|
-
|
26
|
-
else # rails 4.x and later - already has patch
|
27
|
-
require "action_dispatch/http/request"
|
28
|
-
end
|
7
|
+
require "action_dispatch/http/request"
|
29
8
|
|
30
9
|
module OAuth
|
31
10
|
module RequestProxy
|
32
11
|
class ActionControllerRequest < OAuth::RequestProxy::Base
|
33
|
-
proxies(
|
12
|
+
proxies(::ActionDispatch::Request)
|
34
13
|
|
35
14
|
def method
|
36
15
|
request.method.to_s.upcase
|
@@ -50,7 +29,7 @@ module OAuth
|
|
50
29
|
end
|
51
30
|
end
|
52
31
|
|
53
|
-
# Override from OAuth::RequestProxy::Base to avoid
|
32
|
+
# Override from OAuth::RequestProxy::Base to avoid round-trip
|
54
33
|
# conversion to Hash or Array and thus preserve the original
|
55
34
|
# parameter names
|
56
35
|
def parameters_for_signature
|
File without changes
|
@@ -83,7 +83,7 @@ module OAuth
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def oauth_parameters
|
86
|
-
parameters.select { |k,
|
86
|
+
parameters.select { |k, v| OAuth::PARAMETERS.include?(k) && !v.nil? && v != "" }
|
87
87
|
end
|
88
88
|
|
89
89
|
def non_oauth_parameters
|
@@ -127,7 +127,7 @@ module OAuth
|
|
127
127
|
end
|
128
128
|
|
129
129
|
# URI, including OAuth parameters
|
130
|
-
def signed_uri(with_oauth
|
130
|
+
def signed_uri(with_oauth: true)
|
131
131
|
if signed?
|
132
132
|
params = if with_oauth
|
133
133
|
parameters
|
File without changes
|
File without changes
|
File without changes
|