oauth 0.5.6 → 1.1.5
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
- checksums.yaml.gz.sig +4 -0
- data/CHANGELOG.md +848 -0
- data/CITATION.cff +20 -0
- data/CODE_OF_CONDUCT.md +134 -0
- data/CONTRIBUTING.md +218 -0
- data/FUNDING.md +77 -0
- data/LICENSE.txt +22 -0
- data/README.md +662 -0
- data/REEK +2 -0
- data/RUBOCOP.md +71 -0
- data/SECURITY.md +24 -0
- data/lib/oauth/auth_sanitizer.rb +36 -0
- data/lib/oauth/client/action_controller_request.rb +33 -22
- data/lib/oauth/client/em_http.rb +110 -103
- data/lib/oauth/client/helper.rb +87 -82
- data/lib/oauth/client/net_http.rb +140 -107
- data/lib/oauth/client.rb +2 -0
- data/lib/oauth/consumer.rb +222 -141
- data/lib/oauth/errors/error.rb +2 -0
- data/lib/oauth/errors/problem.rb +4 -1
- data/lib/oauth/errors/unauthorized.rb +7 -1
- data/lib/oauth/errors.rb +5 -3
- data/lib/oauth/helper.rb +48 -18
- data/lib/oauth/oauth.rb +31 -7
- data/lib/oauth/oauth_test_helper.rb +6 -4
- data/lib/oauth/optional.rb +20 -0
- data/lib/oauth/request_proxy/action_controller_request.rb +53 -71
- data/lib/oauth/request_proxy/action_dispatch_request.rb +42 -4
- data/lib/oauth/request_proxy/base.rb +146 -131
- data/lib/oauth/request_proxy/curb_request.rb +49 -43
- data/lib/oauth/request_proxy/em_http_request.rb +60 -49
- data/lib/oauth/request_proxy/jabber_request.rb +19 -9
- data/lib/oauth/request_proxy/mock_request.rb +5 -3
- data/lib/oauth/request_proxy/net_http.rb +61 -54
- data/lib/oauth/request_proxy/rack_request.rb +31 -31
- data/lib/oauth/request_proxy/rest_client_request.rb +55 -50
- data/lib/oauth/request_proxy/typhoeus_request.rb +51 -45
- data/lib/oauth/request_proxy.rb +21 -14
- data/lib/oauth/server.rb +18 -12
- data/lib/oauth/signature/base.rb +88 -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 +53 -38
- data/lib/oauth/signature.rb +41 -34
- data/lib/oauth/token.rb +7 -5
- data/lib/oauth/tokens/access_token.rb +6 -4
- data/lib/oauth/tokens/consumer_token.rb +11 -7
- data/lib/oauth/tokens/request_token.rb +17 -10
- data/lib/oauth/tokens/server_token.rb +2 -1
- data/lib/oauth/tokens/token.rb +15 -1
- data/lib/oauth/version.rb +6 -1
- data/lib/oauth.rb +18 -9
- data/sig/oauth/consumer.rbs +9 -0
- data/sig/oauth/signature/base.rbs +12 -0
- data/sig/oauth/tokens/token.rbs +8 -0
- data.tar.gz.sig +3 -0
- metadata +301 -82
- metadata.gz.sig +2 -0
- data/LICENSE +0 -20
- data/README.rdoc +0 -88
- data/TODO +0 -32
- 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,23 +1,44 @@
|
|
|
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
|
|
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[
|
|
12
|
-
if File.exist?(ENV[
|
|
13
|
-
CA_FILE = ENV[
|
|
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
|
-
|
|
20
|
-
CA_FILES = %
|
|
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,53 @@ module OAuth
|
|
|
27
48
|
end
|
|
28
49
|
CA_FILE = nil unless defined?(CA_FILE)
|
|
29
50
|
|
|
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
|
-
|
|
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
|
+
)
|
|
66
94
|
|
|
67
95
|
attr_accessor :options, :key, :secret
|
|
68
|
-
|
|
96
|
+
filtered_attributes :secret
|
|
97
|
+
attr_writer :site, :http
|
|
69
98
|
|
|
70
99
|
# Create a new consumer instance by passing it a configuration hash:
|
|
71
100
|
#
|
|
@@ -75,7 +104,8 @@ module OAuth
|
|
|
75
104
|
# :http_method => :post,
|
|
76
105
|
# :request_token_path => "/oauth/example/request_token.php",
|
|
77
106
|
# :access_token_path => "/oauth/example/access_token.php",
|
|
78
|
-
# :authorize_path => "/oauth/example/authorize.php"
|
|
107
|
+
# :authorize_path => "/oauth/example/authorize.php",
|
|
108
|
+
# :body_hash_enabled => false
|
|
79
109
|
# })
|
|
80
110
|
#
|
|
81
111
|
# Start the process by requesting a token
|
|
@@ -90,14 +120,12 @@ module OAuth
|
|
|
90
120
|
# @photos=@access_token.get('/photos.xml')
|
|
91
121
|
#
|
|
92
122
|
def initialize(consumer_key, consumer_secret, options = {})
|
|
93
|
-
@key
|
|
123
|
+
@key = consumer_key
|
|
94
124
|
@secret = consumer_secret
|
|
95
125
|
|
|
96
126
|
# ensure that keys are symbols
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
opts
|
|
100
|
-
end)
|
|
127
|
+
snaky_options = SnakyHash::SymbolKeyed.new(options)
|
|
128
|
+
@options = @@default_options.merge(snaky_options)
|
|
101
129
|
end
|
|
102
130
|
|
|
103
131
|
# The default http method
|
|
@@ -106,14 +134,12 @@ module OAuth
|
|
|
106
134
|
end
|
|
107
135
|
|
|
108
136
|
def debug_output
|
|
109
|
-
@debug_output ||=
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
@options[:debug_output]
|
|
116
|
-
end
|
|
137
|
+
@debug_output ||= case @options[:debug_output]
|
|
138
|
+
when nil, false
|
|
139
|
+
when true
|
|
140
|
+
$stdout
|
|
141
|
+
else
|
|
142
|
+
@options[:debug_output]
|
|
117
143
|
end
|
|
118
144
|
end
|
|
119
145
|
|
|
@@ -125,45 +151,92 @@ module OAuth
|
|
|
125
151
|
# Contains the root URI for this site
|
|
126
152
|
def uri(custom_uri = nil)
|
|
127
153
|
if custom_uri
|
|
128
|
-
@uri
|
|
154
|
+
@uri = custom_uri
|
|
129
155
|
@http = create_http # yike, oh well. less intrusive this way
|
|
130
|
-
else
|
|
156
|
+
else # if no custom passed, we use existing, which, if unset, is set to site uri
|
|
131
157
|
@uri ||= URI.parse(site)
|
|
132
158
|
end
|
|
133
159
|
end
|
|
134
160
|
|
|
161
|
+
# Exchanges a verified Request Token for an Access Token.
|
|
162
|
+
#
|
|
163
|
+
# OAuth 1.0 vs 1.0a:
|
|
164
|
+
# - 1.0a requires including oauth_verifier (as returned by the Provider after
|
|
165
|
+
# user authorization) when performing this exchange in a 3‑legged flow.
|
|
166
|
+
# - 1.0 flows did not include oauth_verifier.
|
|
167
|
+
#
|
|
168
|
+
# Usage (3‑legged):
|
|
169
|
+
# access_token = request_token.get_access_token(oauth_verifier: params[:oauth_verifier])
|
|
170
|
+
#
|
|
171
|
+
# @param request_token [OAuth::RequestToken] The authorized request token
|
|
172
|
+
# @param request_options [Hash] OAuth or request options (include :oauth_verifier for 1.0a)
|
|
173
|
+
# @param arguments [Array] Optional POST body and headers
|
|
174
|
+
# @yield [response_body] If a block is given, yields the raw response body.
|
|
175
|
+
# @return [OAuth::AccessToken]
|
|
135
176
|
def get_access_token(request_token, request_options = {}, *arguments, &block)
|
|
136
|
-
response = token_request(
|
|
177
|
+
response = token_request(
|
|
178
|
+
http_method,
|
|
179
|
+
(access_token_url? ? access_token_url : access_token_path),
|
|
180
|
+
request_token,
|
|
181
|
+
request_options,
|
|
182
|
+
*arguments,
|
|
183
|
+
&block
|
|
184
|
+
)
|
|
137
185
|
OAuth::AccessToken.from_hash(self, response)
|
|
138
186
|
end
|
|
139
187
|
|
|
140
188
|
# Makes a request to the service for a new OAuth::RequestToken
|
|
141
189
|
#
|
|
142
|
-
#
|
|
190
|
+
# Example:
|
|
191
|
+
# @request_token = @consumer.get_request_token
|
|
143
192
|
#
|
|
144
193
|
# To include OAuth parameters:
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
#
|
|
194
|
+
# @request_token = @consumer.get_request_token(
|
|
195
|
+
# oauth_callback: "http://example.com/cb"
|
|
196
|
+
# )
|
|
148
197
|
#
|
|
149
198
|
# To include application-specific parameters:
|
|
199
|
+
# @request_token = @consumer.get_request_token({}, foo: "bar")
|
|
200
|
+
#
|
|
201
|
+
# OAuth 1.0 vs 1.0a:
|
|
202
|
+
# - In 1.0a, the Consumer SHOULD send oauth_callback when obtaining a request token
|
|
203
|
+
# (or explicitly use OUT_OF_BAND) and the Provider MUST include
|
|
204
|
+
# oauth_callback_confirmed=true in the response.
|
|
205
|
+
# - This library defaults oauth_callback to OUT_OF_BAND ("oob") when not provided,
|
|
206
|
+
# which works for both 1.0 and 1.0a, and mirrors common provider behavior.
|
|
207
|
+
# - The oauth_callback_confirmed response is parsed by the token classes; it is not
|
|
208
|
+
# part of the signature base string and thus is not signed.
|
|
150
209
|
#
|
|
151
|
-
#
|
|
210
|
+
# TODO: In a future major release, oauth_callback may be made mandatory unless
|
|
211
|
+
# request_options[:exclude_callback] is set, to reflect 1.0a guidance.
|
|
152
212
|
#
|
|
153
|
-
#
|
|
213
|
+
# @param request_options [Hash] OAuth options for the request. Notably
|
|
214
|
+
# :oauth_callback can be set to a URL, or OAuth::OUT_OF_BAND ("oob").
|
|
215
|
+
# @param arguments [Array] Optional POST body and headers
|
|
216
|
+
# @yield [response_body] If a block is given, yields the raw response body.
|
|
217
|
+
# @return [OAuth::RequestToken]
|
|
154
218
|
def get_request_token(request_options = {}, *arguments, &block)
|
|
155
219
|
# if oauth_callback wasn't provided, it is assumed that oauth_verifiers
|
|
156
220
|
# will be exchanged out of band
|
|
157
221
|
request_options[:oauth_callback] ||= OAuth::OUT_OF_BAND unless request_options[:exclude_callback]
|
|
158
222
|
|
|
159
|
-
if
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
223
|
+
response = if block
|
|
224
|
+
token_request(
|
|
225
|
+
http_method,
|
|
226
|
+
(request_token_url? ? request_token_url : request_token_path),
|
|
227
|
+
nil,
|
|
228
|
+
request_options,
|
|
229
|
+
*arguments,
|
|
230
|
+
&block
|
|
231
|
+
)
|
|
165
232
|
else
|
|
166
|
-
|
|
233
|
+
token_request(
|
|
234
|
+
http_method,
|
|
235
|
+
(request_token_url? ? request_token_url : request_token_path),
|
|
236
|
+
nil,
|
|
237
|
+
request_options,
|
|
238
|
+
*arguments,
|
|
239
|
+
)
|
|
167
240
|
end
|
|
168
241
|
OAuth::RequestToken.from_hash(self, response)
|
|
169
242
|
end
|
|
@@ -179,26 +252,27 @@ module OAuth
|
|
|
179
252
|
# @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' })
|
|
180
253
|
#
|
|
181
254
|
def request(http_method, path, token = nil, request_options = {}, *arguments)
|
|
182
|
-
|
|
255
|
+
unless %r{^/} =~ path
|
|
183
256
|
@http = create_http(path)
|
|
184
|
-
|
|
185
|
-
path = "#{
|
|
257
|
+
uri = URI.parse(path)
|
|
258
|
+
path = "#{uri.path}#{"?#{uri.query}" if uri.query}"
|
|
186
259
|
end
|
|
187
260
|
|
|
188
261
|
# override the request with your own, this is useful for file uploads which Net::HTTP does not do
|
|
189
262
|
req = create_signed_request(http_method, path, token, request_options, *arguments)
|
|
190
|
-
return
|
|
263
|
+
return if block_given? && (yield(req) == :done)
|
|
264
|
+
|
|
191
265
|
rsp = http.request(req)
|
|
192
266
|
# check for an error reported by the Problem Reporting extension
|
|
193
|
-
# (
|
|
267
|
+
# (https://wiki.oauth.net/ProblemReporting)
|
|
194
268
|
# note: a 200 may actually be an error; check for an oauth_problem key to be sure
|
|
195
269
|
if !(headers = rsp.to_hash["www-authenticate"]).nil? &&
|
|
196
|
-
|
|
197
|
-
|
|
270
|
+
(h = headers.grep(/^OAuth /)).any? &&
|
|
271
|
+
h.first.include?("oauth_problem")
|
|
198
272
|
|
|
199
273
|
# puts "Header: #{h.first}"
|
|
200
274
|
|
|
201
|
-
# TODO doesn't handle broken responses from api.login.yahoo.com
|
|
275
|
+
# TODO: doesn't handle broken responses from api.login.yahoo.com
|
|
202
276
|
# remove debug code when done
|
|
203
277
|
params = OAuth::Helper.parse_header(h.first)
|
|
204
278
|
|
|
@@ -232,24 +306,25 @@ module OAuth
|
|
|
232
306
|
# symbolize keys
|
|
233
307
|
# TODO this could be considered unexpected behavior; symbols or not?
|
|
234
308
|
# TODO this also drops subsequent values from multi-valued keys
|
|
235
|
-
CGI.parse(response.body).
|
|
309
|
+
CGI.parse(response.body).each_with_object({}) do |(k, v), h|
|
|
236
310
|
h[k.strip.to_sym] = v.first
|
|
237
|
-
h[k.strip]
|
|
238
|
-
h
|
|
311
|
+
h[k.strip] = v.first
|
|
239
312
|
end
|
|
240
313
|
end
|
|
241
314
|
when (300..399)
|
|
242
|
-
#
|
|
243
|
-
uri = URI.parse(response[
|
|
315
|
+
# Parse redirect to follow
|
|
316
|
+
uri = URI.parse(response["location"])
|
|
244
317
|
our_uri = URI.parse(site)
|
|
245
318
|
|
|
319
|
+
# Guard against infinite redirects
|
|
320
|
+
response.error! if uri.path == path && our_uri.host == uri.host
|
|
321
|
+
|
|
246
322
|
if uri.path == path && our_uri.host != uri.host
|
|
247
|
-
|
|
248
|
-
|
|
323
|
+
options[:site] = "#{uri.scheme}://#{uri.host}"
|
|
324
|
+
@http = create_http
|
|
249
325
|
end
|
|
250
326
|
|
|
251
|
-
|
|
252
|
-
self.token_request(http_method, uri.path, token, request_options, arguments)
|
|
327
|
+
token_request(http_method, uri.path, token, request_options, arguments)
|
|
253
328
|
when (400..499)
|
|
254
329
|
raise OAuth::Unauthorized, response
|
|
255
330
|
else
|
|
@@ -272,7 +347,8 @@ module OAuth
|
|
|
272
347
|
end
|
|
273
348
|
|
|
274
349
|
def request_endpoint
|
|
275
|
-
return
|
|
350
|
+
return if @options[:request_endpoint].nil?
|
|
351
|
+
|
|
276
352
|
@options[:request_endpoint].to_s
|
|
277
353
|
end
|
|
278
354
|
|
|
@@ -296,37 +372,37 @@ module OAuth
|
|
|
296
372
|
@options[:access_token_path]
|
|
297
373
|
end
|
|
298
374
|
|
|
299
|
-
# TODO this is ugly, rewrite
|
|
375
|
+
# TODO: this is ugly, rewrite
|
|
300
376
|
def request_token_url
|
|
301
|
-
@options[:request_token_url] || site + request_token_path
|
|
377
|
+
@options[:request_token_url] || (site + request_token_path)
|
|
302
378
|
end
|
|
303
379
|
|
|
304
380
|
def request_token_url?
|
|
305
|
-
@options.
|
|
381
|
+
@options.key?(:request_token_url)
|
|
306
382
|
end
|
|
307
383
|
|
|
308
384
|
def authenticate_url
|
|
309
|
-
@options[:authenticate_url] || site + authenticate_path
|
|
385
|
+
@options[:authenticate_url] || (site + authenticate_path)
|
|
310
386
|
end
|
|
311
387
|
|
|
312
388
|
def authenticate_url?
|
|
313
|
-
@options.
|
|
389
|
+
@options.key?(:authenticate_url)
|
|
314
390
|
end
|
|
315
391
|
|
|
316
392
|
def authorize_url
|
|
317
|
-
@options[:authorize_url] || site + authorize_path
|
|
393
|
+
@options[:authorize_url] || (site + authorize_path)
|
|
318
394
|
end
|
|
319
395
|
|
|
320
396
|
def authorize_url?
|
|
321
|
-
@options.
|
|
397
|
+
@options.key?(:authorize_url)
|
|
322
398
|
end
|
|
323
399
|
|
|
324
400
|
def access_token_url
|
|
325
|
-
@options[:access_token_url] || site + access_token_path
|
|
401
|
+
@options[:access_token_url] || (site + access_token_path)
|
|
326
402
|
end
|
|
327
403
|
|
|
328
404
|
def access_token_url?
|
|
329
|
-
@options.
|
|
405
|
+
@options.key?(:access_token_url)
|
|
330
406
|
end
|
|
331
407
|
|
|
332
408
|
def proxy
|
|
@@ -336,37 +412,43 @@ module OAuth
|
|
|
336
412
|
protected
|
|
337
413
|
|
|
338
414
|
# Instantiates the http object
|
|
339
|
-
def create_http(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
if !request_endpoint.nil?
|
|
343
|
-
_url = request_endpoint
|
|
344
|
-
end
|
|
345
|
-
|
|
415
|
+
def create_http(url = nil)
|
|
416
|
+
url = request_endpoint unless request_endpoint.nil?
|
|
346
417
|
|
|
347
|
-
if
|
|
348
|
-
|
|
418
|
+
our_uri = if url.nil? || url[0] =~ %r{^/}
|
|
419
|
+
URI.parse(site)
|
|
349
420
|
else
|
|
350
|
-
|
|
421
|
+
your_uri = URI.parse(url)
|
|
422
|
+
if your_uri.host.nil?
|
|
423
|
+
# If the _url is a path, missing the leading slash, then it won't have a host,
|
|
424
|
+
# and our_uri *must* have a host, so we parse site instead.
|
|
425
|
+
URI.parse(site)
|
|
426
|
+
else
|
|
427
|
+
your_uri
|
|
428
|
+
end
|
|
351
429
|
end
|
|
352
430
|
|
|
353
|
-
|
|
354
431
|
if proxy.nil?
|
|
355
432
|
http_object = Net::HTTP.new(our_uri.host, our_uri.port)
|
|
356
433
|
else
|
|
357
434
|
proxy_uri = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
|
|
358
|
-
http_object = Net::HTTP.new(
|
|
435
|
+
http_object = Net::HTTP.new(
|
|
436
|
+
our_uri.host,
|
|
437
|
+
our_uri.port,
|
|
438
|
+
proxy_uri.host,
|
|
439
|
+
proxy_uri.port,
|
|
440
|
+
proxy_uri.user,
|
|
441
|
+
proxy_uri.password,
|
|
442
|
+
)
|
|
359
443
|
end
|
|
360
444
|
|
|
361
|
-
http_object.use_ssl = (our_uri.scheme ==
|
|
445
|
+
http_object.use_ssl = (our_uri.scheme == "https")
|
|
362
446
|
|
|
363
447
|
if @options[:no_verify]
|
|
364
448
|
http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
365
449
|
else
|
|
366
|
-
ca_file =
|
|
367
|
-
if ca_file
|
|
368
|
-
http_object.ca_file = ca_file
|
|
369
|
-
end
|
|
450
|
+
ca_file = @options[:ca_file] || CA_FILE
|
|
451
|
+
http_object.ca_file = ca_file if ca_file
|
|
370
452
|
http_object.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
371
453
|
http_object.verify_depth = 5
|
|
372
454
|
end
|
|
@@ -374,6 +456,8 @@ module OAuth
|
|
|
374
456
|
http_object.read_timeout = http_object.open_timeout = @options[:timeout] || 60
|
|
375
457
|
http_object.open_timeout = @options[:open_timeout] if @options[:open_timeout]
|
|
376
458
|
http_object.ssl_version = @options[:ssl_version] if @options[:ssl_version]
|
|
459
|
+
http_object.cert = @options[:ssl_client_cert] if @options[:ssl_client_cert]
|
|
460
|
+
http_object.key = @options[:ssl_client_key] if @options[:ssl_client_key]
|
|
377
461
|
http_object.set_debug_output(debug_output) if debug_output
|
|
378
462
|
|
|
379
463
|
http_object
|
|
@@ -383,41 +467,39 @@ module OAuth
|
|
|
383
467
|
def create_http_request(http_method, path, *arguments)
|
|
384
468
|
http_method = http_method.to_sym
|
|
385
469
|
|
|
386
|
-
if [
|
|
387
|
-
data = arguments.shift
|
|
388
|
-
end
|
|
470
|
+
data = arguments.shift if %i[post put patch].include?(http_method)
|
|
389
471
|
|
|
390
472
|
# if the base site contains a path, add it now
|
|
391
473
|
# only add if the site host matches the current http object's host
|
|
392
474
|
# (in case we've specified a full url for token requests)
|
|
393
|
-
uri
|
|
394
|
-
path = uri.path + path if uri.path && uri.path !=
|
|
475
|
+
uri = URI.parse(site)
|
|
476
|
+
path = uri.path + path if uri.path && uri.path != "/" && uri.host == http.address
|
|
395
477
|
|
|
396
478
|
headers = arguments.first.is_a?(Hash) ? arguments.shift : {}
|
|
397
479
|
|
|
398
480
|
case http_method
|
|
399
481
|
when :post
|
|
400
|
-
request = Net::HTTP::Post.new(path,headers)
|
|
401
|
-
request["Content-Length"] =
|
|
482
|
+
request = Net::HTTP::Post.new(path, headers)
|
|
483
|
+
request["Content-Length"] = "0" # Default to 0
|
|
402
484
|
when :put
|
|
403
|
-
request = Net::HTTP::Put.new(path,headers)
|
|
404
|
-
request["Content-Length"] =
|
|
485
|
+
request = Net::HTTP::Put.new(path, headers)
|
|
486
|
+
request["Content-Length"] = "0" # Default to 0
|
|
405
487
|
when :patch
|
|
406
|
-
request = Net::HTTP::Patch.new(path,headers)
|
|
407
|
-
request["Content-Length"] =
|
|
488
|
+
request = Net::HTTP::Patch.new(path, headers)
|
|
489
|
+
request["Content-Length"] = "0" # Default to 0
|
|
408
490
|
when :get
|
|
409
|
-
request = Net::HTTP::Get.new(path,headers)
|
|
491
|
+
request = Net::HTTP::Get.new(path, headers)
|
|
410
492
|
when :delete
|
|
411
|
-
request =
|
|
493
|
+
request = Net::HTTP::Delete.new(path, headers)
|
|
412
494
|
when :head
|
|
413
|
-
request = Net::HTTP::Head.new(path,headers)
|
|
495
|
+
request = Net::HTTP::Head.new(path, headers)
|
|
414
496
|
else
|
|
415
|
-
raise ArgumentError, "Don't know how to handle http_method: :#{http_method
|
|
497
|
+
raise ArgumentError, "Don't know how to handle http_method: :#{http_method}"
|
|
416
498
|
end
|
|
417
499
|
|
|
418
500
|
if data.is_a?(Hash)
|
|
419
501
|
request.body = OAuth::Helper.normalize(data)
|
|
420
|
-
request.content_type =
|
|
502
|
+
request.content_type = "application/x-www-form-urlencoded"
|
|
421
503
|
elsif data
|
|
422
504
|
if data.respond_to?(:read)
|
|
423
505
|
request.body_stream = data
|
|
@@ -437,13 +519,12 @@ module OAuth
|
|
|
437
519
|
request
|
|
438
520
|
end
|
|
439
521
|
|
|
440
|
-
def marshal_dump(*
|
|
441
|
-
{:
|
|
522
|
+
def marshal_dump(*_args)
|
|
523
|
+
{key: @key, secret: @secret, options: @options}
|
|
442
524
|
end
|
|
443
525
|
|
|
444
526
|
def marshal_load(data)
|
|
445
527
|
initialize(data[:key], data[:secret], data[:options])
|
|
446
528
|
end
|
|
447
|
-
|
|
448
529
|
end
|
|
449
530
|
end
|
data/lib/oauth/errors/error.rb
CHANGED
data/lib/oauth/errors/problem.rb
CHANGED
|
@@ -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
|
|
10
|
+
@params = params
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
def to_s
|
|
@@ -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