oauth 0.5.6 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +478 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/CONTRIBUTING.md +23 -0
- data/LICENSE +18 -17
- data/README.md +383 -0
- data/SECURITY.md +20 -0
- data/bin/oauth +10 -6
- data/lib/oauth/cli/authorize_command.rb +57 -55
- data/lib/oauth/cli/base_command.rb +163 -157
- data/lib/oauth/cli/help_command.rb +9 -5
- data/lib/oauth/cli/query_command.rb +26 -17
- data/lib/oauth/cli/sign_command.rb +58 -55
- data/lib/oauth/cli/version_command.rb +8 -4
- data/lib/oauth/cli.rb +21 -19
- data/lib/oauth/client/action_controller_request.rb +23 -21
- data/lib/oauth/client/em_http.rb +101 -99
- data/lib/oauth/client/helper.rb +83 -82
- data/lib/oauth/client/net_http.rb +112 -105
- data/lib/oauth/client.rb +2 -0
- data/lib/oauth/consumer.rb +157 -135
- data/lib/oauth/errors/error.rb +2 -0
- data/lib/oauth/errors/problem.rb +3 -0
- data/lib/oauth/errors/unauthorized.rb +7 -1
- data/lib/oauth/errors.rb +5 -3
- data/lib/oauth/helper.rb +26 -18
- data/lib/oauth/oauth.rb +6 -4
- data/lib/oauth/oauth_test_helper.rb +6 -4
- data/lib/oauth/request_proxy/action_controller_request.rb +56 -57
- data/lib/oauth/request_proxy/action_dispatch_request.rb +8 -4
- data/lib/oauth/request_proxy/base.rb +136 -132
- data/lib/oauth/request_proxy/curb_request.rb +49 -43
- data/lib/oauth/request_proxy/em_http_request.rb +59 -49
- data/lib/oauth/request_proxy/jabber_request.rb +12 -9
- data/lib/oauth/request_proxy/mock_request.rb +5 -3
- data/lib/oauth/request_proxy/net_http.rb +63 -54
- data/lib/oauth/request_proxy/rack_request.rb +35 -31
- data/lib/oauth/request_proxy/rest_client_request.rb +54 -50
- data/lib/oauth/request_proxy/typhoeus_request.rb +51 -45
- data/lib/oauth/request_proxy.rb +7 -4
- data/lib/oauth/server.rb +14 -12
- data/lib/oauth/signature/base.rb +80 -71
- data/lib/oauth/signature/hmac/sha1.rb +16 -10
- data/lib/oauth/signature/hmac/sha256.rb +16 -10
- 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 +7 -5
- data/lib/oauth/tokens/access_token.rb +5 -3
- 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 +17 -9
- metadata +94 -98
- data/README.rdoc +0 -88
data/lib/oauth/consumer.rb
CHANGED
@@ -1,23 +1,26 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
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
|
9
11
|
class Consumer
|
10
12
|
# determine the certificate authority path to verify SSL certs
|
11
|
-
if ENV[
|
12
|
-
if File.exist?(ENV[
|
13
|
-
CA_FILE = ENV[
|
13
|
+
if ENV["SSL_CERT_FILE"]
|
14
|
+
if File.exist?(ENV["SSL_CERT_FILE"])
|
15
|
+
CA_FILE = ENV["SSL_CERT_FILE"]
|
14
16
|
else
|
15
17
|
raise "The SSL CERT provided does not exist."
|
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
|
|
@@ -154,17 +162,23 @@ module OAuth
|
|
154
162
|
def get_request_token(request_options = {}, *arguments, &block)
|
155
163
|
# if oauth_callback wasn't provided, it is assumed that oauth_verifiers
|
156
164
|
# will be exchanged out of band
|
157
|
-
|
158
|
-
|
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)
|
165
|
-
else
|
166
|
-
response = token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil, request_options, *arguments)
|
165
|
+
unless request_options[:exclude_callback]
|
166
|
+
request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND
|
167
167
|
end
|
168
|
+
|
169
|
+
response = if block
|
170
|
+
token_request(
|
171
|
+
http_method,
|
172
|
+
(request_token_url? ? request_token_url : request_token_path),
|
173
|
+
nil,
|
174
|
+
request_options,
|
175
|
+
*arguments,
|
176
|
+
&block
|
177
|
+
)
|
178
|
+
else
|
179
|
+
token_request(http_method, (request_token_url? ? request_token_url : request_token_path), nil,
|
180
|
+
request_options, *arguments)
|
181
|
+
end
|
168
182
|
OAuth::RequestToken.from_hash(self, response)
|
169
183
|
end
|
170
184
|
|
@@ -179,7 +193,7 @@ module OAuth
|
|
179
193
|
# @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
|
180
194
|
#
|
181
195
|
def request(http_method, path, token = nil, request_options = {}, *arguments)
|
182
|
-
|
196
|
+
unless %r{^/}.match?(path)
|
183
197
|
@http = create_http(path)
|
184
198
|
_uri = URI.parse(path)
|
185
199
|
path = "#{_uri.path}#{_uri.query ? "?#{_uri.query}" : ""}"
|
@@ -187,18 +201,19 @@ module OAuth
|
|
187
201
|
|
188
202
|
# override the request with your own, this is useful for file uploads which Net::HTTP does not do
|
189
203
|
req = create_signed_request(http_method, path, token, request_options, *arguments)
|
190
|
-
return nil if block_given?
|
204
|
+
return nil if block_given? && (yield(req) == :done)
|
205
|
+
|
191
206
|
rsp = http.request(req)
|
192
207
|
# check for an error reported by the Problem Reporting extension
|
193
|
-
# (
|
208
|
+
# (https://wiki.oauth.net/ProblemReporting)
|
194
209
|
# note: a 200 may actually be an error; check for an oauth_problem key to be sure
|
195
210
|
if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
|
196
|
-
|
197
|
-
|
211
|
+
(h = headers.grep(/^OAuth /)).any? &&
|
212
|
+
h.first.include?("oauth_problem")
|
198
213
|
|
199
214
|
# puts "Header: #{h.first}"
|
200
215
|
|
201
|
-
# TODO doesn't handle broken responses from api.login.yahoo.com
|
216
|
+
# TODO: doesn't handle broken responses from api.login.yahoo.com
|
202
217
|
# remove debug code when done
|
203
218
|
params = OAuth::Helper.parse_header(h.first)
|
204
219
|
|
@@ -232,24 +247,25 @@ module OAuth
|
|
232
247
|
# symbolize keys
|
233
248
|
# TODO this could be considered unexpected behavior; symbols or not?
|
234
249
|
# TODO this also drops subsequent values from multi-valued keys
|
235
|
-
CGI.parse(response.body).
|
250
|
+
CGI.parse(response.body).each_with_object({}) do |(k, v), h|
|
236
251
|
h[k.strip.to_sym] = v.first
|
237
252
|
h[k.strip] = v.first
|
238
|
-
h
|
239
253
|
end
|
240
254
|
end
|
241
255
|
when (300..399)
|
242
|
-
#
|
243
|
-
uri = URI.parse(response[
|
256
|
+
# Parse redirect to follow
|
257
|
+
uri = URI.parse(response["location"])
|
244
258
|
our_uri = URI.parse(site)
|
245
259
|
|
260
|
+
# Guard against infinite redirects
|
261
|
+
response.error! if uri.path == path && our_uri.host == uri.host
|
262
|
+
|
246
263
|
if uri.path == path && our_uri.host != uri.host
|
247
|
-
|
248
|
-
|
264
|
+
options[:site] = "#{uri.scheme}://#{uri.host}"
|
265
|
+
@http = create_http
|
249
266
|
end
|
250
267
|
|
251
|
-
|
252
|
-
self.token_request(http_method, uri.path, token, request_options, arguments)
|
268
|
+
token_request(http_method, uri.path, token, request_options, arguments)
|
253
269
|
when (400..499)
|
254
270
|
raise OAuth::Unauthorized, response
|
255
271
|
else
|
@@ -273,6 +289,7 @@ module OAuth
|
|
273
289
|
|
274
290
|
def request_endpoint
|
275
291
|
return nil if @options[:request_endpoint].nil?
|
292
|
+
|
276
293
|
@options[:request_endpoint].to_s
|
277
294
|
end
|
278
295
|
|
@@ -296,37 +313,37 @@ module OAuth
|
|
296
313
|
@options[:access_token_path]
|
297
314
|
end
|
298
315
|
|
299
|
-
# TODO this is ugly, rewrite
|
316
|
+
# TODO: this is ugly, rewrite
|
300
317
|
def request_token_url
|
301
|
-
@options[:request_token_url] || site + request_token_path
|
318
|
+
@options[:request_token_url] || (site + request_token_path)
|
302
319
|
end
|
303
320
|
|
304
321
|
def request_token_url?
|
305
|
-
@options.
|
322
|
+
@options.key?(:request_token_url)
|
306
323
|
end
|
307
324
|
|
308
325
|
def authenticate_url
|
309
|
-
@options[:authenticate_url] || site + authenticate_path
|
326
|
+
@options[:authenticate_url] || (site + authenticate_path)
|
310
327
|
end
|
311
328
|
|
312
329
|
def authenticate_url?
|
313
|
-
@options.
|
330
|
+
@options.key?(:authenticate_url)
|
314
331
|
end
|
315
332
|
|
316
333
|
def authorize_url
|
317
|
-
@options[:authorize_url] || site + authorize_path
|
334
|
+
@options[:authorize_url] || (site + authorize_path)
|
318
335
|
end
|
319
336
|
|
320
337
|
def authorize_url?
|
321
|
-
@options.
|
338
|
+
@options.key?(:authorize_url)
|
322
339
|
end
|
323
340
|
|
324
341
|
def access_token_url
|
325
|
-
@options[:access_token_url] || site + access_token_path
|
342
|
+
@options[:access_token_url] || (site + access_token_path)
|
326
343
|
end
|
327
344
|
|
328
345
|
def access_token_url?
|
329
|
-
@options.
|
346
|
+
@options.key?(:access_token_url)
|
330
347
|
end
|
331
348
|
|
332
349
|
def proxy
|
@@ -337,43 +354,49 @@ module OAuth
|
|
337
354
|
|
338
355
|
# Instantiates the http object
|
339
356
|
def create_http(_url = nil)
|
340
|
-
|
341
|
-
|
342
|
-
if
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
357
|
+
_url = request_endpoint unless request_endpoint.nil?
|
358
|
+
|
359
|
+
our_uri = if _url.nil? || _url[0] =~ %r{^/}
|
360
|
+
URI.parse(site)
|
361
|
+
else
|
362
|
+
your_uri = URI.parse(_url)
|
363
|
+
if your_uri.host.nil?
|
364
|
+
# If the _url is a path, missing the leading slash, then it won't have a host,
|
365
|
+
# and our_uri *must* have a host, so we parse site instead.
|
366
|
+
URI.parse(site)
|
367
|
+
else
|
368
|
+
your_uri
|
369
|
+
end
|
370
|
+
end
|
353
371
|
|
354
372
|
if proxy.nil?
|
355
373
|
http_object = Net::HTTP.new(our_uri.host, our_uri.port)
|
356
374
|
else
|
357
375
|
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,
|
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)
|
359
378
|
end
|
360
379
|
|
361
|
-
http_object.use_ssl = (our_uri.scheme ==
|
380
|
+
http_object.use_ssl = (our_uri.scheme == "https")
|
362
381
|
|
363
382
|
if @options[:no_verify]
|
364
383
|
http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
365
384
|
else
|
366
|
-
ca_file =
|
367
|
-
if ca_file
|
368
|
-
http_object.ca_file = ca_file
|
369
|
-
end
|
385
|
+
ca_file = @options[:ca_file] || CA_FILE
|
386
|
+
http_object.ca_file = ca_file if ca_file
|
370
387
|
http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
371
388
|
http_object.verify_depth = 5
|
372
389
|
end
|
373
390
|
|
374
391
|
http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 60
|
375
|
-
|
392
|
+
if @options[:open_timeout]
|
393
|
+
http_object.open_timeout = @options[:open_timeout]
|
394
|
+
end
|
376
395
|
http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
|
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]
|
377
400
|
http_object.set_debug_output(debug_output) if debug_output
|
378
401
|
|
379
402
|
http_object
|
@@ -383,41 +406,41 @@ module OAuth
|
|
383
406
|
def create_http_request(http_method, path, *arguments)
|
384
407
|
http_method = http_method.to_sym
|
385
408
|
|
386
|
-
if [
|
387
|
-
data = arguments.shift
|
388
|
-
end
|
409
|
+
data = arguments.shift if %i[post put patch].include?(http_method)
|
389
410
|
|
390
411
|
# if the base site contains a path, add it now
|
391
412
|
# only add if the site host matches the current http object's host
|
392
413
|
# (in case we've specified a full url for token requests)
|
393
|
-
uri
|
394
|
-
|
414
|
+
uri = URI.parse(site)
|
415
|
+
if uri.path && uri.path != "/" && uri.host == http.address
|
416
|
+
path = uri.path + path
|
417
|
+
end
|
395
418
|
|
396
419
|
headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
|
397
420
|
|
398
421
|
case http_method
|
399
422
|
when :post
|
400
|
-
request = Net::HTTP::Post.new(path,headers)
|
401
|
-
request["Content-Length"] =
|
423
|
+
request = Net::HTTP::Post.new(path, headers)
|
424
|
+
request["Content-Length"] = "0" # Default to 0
|
402
425
|
when :put
|
403
|
-
request = Net::HTTP::Put.new(path,headers)
|
404
|
-
request["Content-Length"] =
|
426
|
+
request = Net::HTTP::Put.new(path, headers)
|
427
|
+
request["Content-Length"] = "0" # Default to 0
|
405
428
|
when :patch
|
406
|
-
request = Net::HTTP::Patch.new(path,headers)
|
407
|
-
request["Content-Length"] =
|
429
|
+
request = Net::HTTP::Patch.new(path, headers)
|
430
|
+
request["Content-Length"] = "0" # Default to 0
|
408
431
|
when :get
|
409
|
-
request = Net::HTTP::Get.new(path,headers)
|
432
|
+
request = Net::HTTP::Get.new(path, headers)
|
410
433
|
when :delete
|
411
|
-
request =
|
434
|
+
request = Net::HTTP::Delete.new(path, headers)
|
412
435
|
when :head
|
413
|
-
request = Net::HTTP::Head.new(path,headers)
|
436
|
+
request = Net::HTTP::Head.new(path, headers)
|
414
437
|
else
|
415
|
-
raise ArgumentError, "Don't know how to handle http_method: :#{http_method
|
438
|
+
raise ArgumentError, "Don't know how to handle http_method: :#{http_method}"
|
416
439
|
end
|
417
440
|
|
418
441
|
if data.is_a?(Hash)
|
419
442
|
request.body = OAuth::Helper.normalize(data)
|
420
|
-
request.content_type =
|
443
|
+
request.content_type = "application/x-www-form-urlencoded"
|
421
444
|
elsif data
|
422
445
|
if data.respond_to?(:read)
|
423
446
|
request.body_stream = data
|
@@ -437,13 +460,12 @@ module OAuth
|
|
437
460
|
request
|
438
461
|
end
|
439
462
|
|
440
|
-
def marshal_dump(*
|
441
|
-
{:
|
463
|
+
def marshal_dump(*_args)
|
464
|
+
{ key: @key, secret: @secret, options: @options }
|
442
465
|
end
|
443
466
|
|
444
467
|
def marshal_load(data)
|
445
468
|
initialize(data[:key], data[:secret], data[:options])
|
446
469
|
end
|
447
|
-
|
448
470
|
end
|
449
471
|
end
|
data/lib/oauth/errors/error.rb
CHANGED
data/lib/oauth/errors/problem.rb
CHANGED
@@ -1,12 +1,18 @@
|
|
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
|
|
8
12
|
def to_s
|
9
|
-
|
13
|
+
return "401 Unauthorized" if request.nil?
|
14
|
+
|
15
|
+
"#{request.code} #{request.message}"
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|
data/lib/oauth/errors.rb
CHANGED
data/lib/oauth/helper.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "time"
|
4
|
+
require "openssl"
|
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
|
#
|
@@ -19,18 +22,18 @@ module OAuth
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def unescape(value)
|
22
|
-
URI::DEFAULT_PARSER.unescape(value.gsub(
|
25
|
+
URI::DEFAULT_PARSER.unescape(value.gsub("+", "%2B"))
|
23
26
|
end
|
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)
|
28
|
-
Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/,
|
30
|
+
def generate_key(size = 32)
|
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,22 +46,27 @@ 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
|
50
|
-
values.
|
51
|
-
|
54
|
+
if values[0].is_a?(Hash)
|
55
|
+
normalize_nested_query(values, k)
|
56
|
+
else
|
57
|
+
values.sort.collect do |v|
|
58
|
+
[escape(k), escape(v)].join("=")
|
59
|
+
end
|
52
60
|
end
|
53
|
-
|
61
|
+
when Hash
|
54
62
|
normalize_nested_query(values, k)
|
55
63
|
else
|
56
|
-
[escape(k),escape(values)]
|
64
|
+
[escape(k), escape(values)].join("=")
|
57
65
|
end
|
58
66
|
end * "&"
|
59
67
|
end
|
60
68
|
|
61
|
-
#Returns a string representation of the Hash like in URL query string
|
69
|
+
# Returns a string representation of the Hash like in URL query string
|
62
70
|
# build_nested_query({:level_1 => {:level_2 => ['value_1','value_2']}}, 'prefix'))
|
63
71
|
# #=> ["prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_1", "prefix%5Blevel_1%5D%5Blevel_2%5D%5B%5D=value_2"]
|
64
72
|
def normalize_nested_query(value, prefix = nil)
|
@@ -72,7 +80,7 @@ module OAuth
|
|
72
80
|
normalize_nested_query(v, prefix ? "#{prefix}[#{k}]" : k)
|
73
81
|
end.flatten.sort
|
74
82
|
else
|
75
|
-
[escape(prefix), escape(value)]
|
83
|
+
[escape(prefix), escape(value)].join("=")
|
76
84
|
end
|
77
85
|
end
|
78
86
|
|
@@ -86,16 +94,16 @@ module OAuth
|
|
86
94
|
#
|
87
95
|
def parse_header(header)
|
88
96
|
# decompose
|
89
|
-
params = header[6,header.length].split(/[,=&]/)
|
97
|
+
params = header[6, header.length].split(/[,=&]/)
|
90
98
|
|
91
99
|
# odd number of arguments - must be a malformed header.
|
92
|
-
raise OAuth::Problem
|
100
|
+
raise OAuth::Problem, "Invalid authorization header" if params.size.odd?
|
93
101
|
|
94
102
|
params.map! do |v|
|
95
103
|
# strip and unescape
|
96
104
|
val = unescape(v.strip)
|
97
105
|
# strip quotes
|
98
|
-
val.sub(
|
106
|
+
val.sub(/^"(.*)"$/, '\1')
|
99
107
|
end
|
100
108
|
|
101
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
|