signet 0.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.
- data/CHANGELOG +3 -0
- data/LICENSE +202 -0
- data/README +47 -0
- data/Rakefile +59 -0
- data/lib/compat/digest/hmac.rb +104 -0
- data/lib/compat/securerandom.rb +202 -0
- data/lib/signet.rb +18 -0
- data/lib/signet/errors.rb +38 -0
- data/lib/signet/oauth_1.rb +456 -0
- data/lib/signet/oauth_1/client.rb +1012 -0
- data/lib/signet/oauth_1/credential.rb +119 -0
- data/lib/signet/oauth_1/signature_methods/hmac_sha1.rb +31 -0
- data/lib/signet/version.rb +26 -0
- data/spec/force_compat/digest/hmac.rb +1 -0
- data/spec/force_compat/securerandom.rb +1 -0
- data/spec/signet/oauth_1/client_spec.rb +687 -0
- data/spec/signet/oauth_1/credential_spec.rb +163 -0
- data/spec/signet/oauth_1/services/google_spec.rb +234 -0
- data/spec/signet/oauth_1/signature_methods/hmac_sha1_spec.rb +62 -0
- data/spec/signet/oauth_1_spec.rb +883 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/clobber.rake +2 -0
- data/tasks/gem.rake +71 -0
- data/tasks/git.rake +40 -0
- data/tasks/metrics.rake +41 -0
- data/tasks/rdoc.rake +26 -0
- data/tasks/rubyforge.rake +100 -0
- data/tasks/spec.rake +69 -0
- data/tasks/yard.rake +26 -0
- data/website/index.html +95 -0
- metadata +195 -0
data/lib/signet.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright (C) 2010 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'signet/version'
|
16
|
+
|
17
|
+
module Signet #:nodoc:
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Copyright (C) 2010 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Signet #:nodoc:
|
16
|
+
class AuthorizationError < StandardError
|
17
|
+
##
|
18
|
+
# Creates a new authentication error.
|
19
|
+
#
|
20
|
+
# @param [String] message
|
21
|
+
# A message describing the error.
|
22
|
+
# @param [Array] request
|
23
|
+
# A tuple of method, uri, headers, and body. Optional.
|
24
|
+
# @param [Array] response
|
25
|
+
# A tuple of status, headers, and body. Optional.
|
26
|
+
def initialize(message, request=nil, response=nil)
|
27
|
+
super(message)
|
28
|
+
@request = request
|
29
|
+
@response = response
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# The HTTP response that triggered this authentication error.
|
34
|
+
#
|
35
|
+
# @return [Array] A tuple of status, headers, and body.
|
36
|
+
attr_reader :response
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,456 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'securerandom'
|
5
|
+
rescue LoadError
|
6
|
+
require 'compat/securerandom'
|
7
|
+
end
|
8
|
+
|
9
|
+
module Signet #:nodoc:
|
10
|
+
module OAuth1
|
11
|
+
OUT_OF_BAND = 'oob'
|
12
|
+
|
13
|
+
##
|
14
|
+
# Converts a value to a percent-encoded <code>String</code> according to
|
15
|
+
# the rules given in RFC 5849. All non-unreserved characters are
|
16
|
+
# percent-encoded.
|
17
|
+
#
|
18
|
+
# @param [Symbol, #to_str] value The value to be encoded.
|
19
|
+
#
|
20
|
+
# @return [String] The percent-encoded value.
|
21
|
+
def self.encode(value)
|
22
|
+
value = value.to_s if value.kind_of?(Symbol)
|
23
|
+
return Addressable::URI.encode_component(
|
24
|
+
value,
|
25
|
+
Addressable::URI::CharacterClasses::UNRESERVED
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Converts a percent-encoded String to an unencoded value.
|
31
|
+
#
|
32
|
+
# @param [#to_str] value
|
33
|
+
# The percent-encoded <code>String</code> to be unencoded.
|
34
|
+
#
|
35
|
+
# @return [String] The unencoded value.
|
36
|
+
def self.unencode(value)
|
37
|
+
return Addressable::URI.unencode_component(value)
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Returns a timestamp suitable for use as an <code>'oauth_timestamp'</code>
|
42
|
+
# value.
|
43
|
+
#
|
44
|
+
# @return [String] The current timestamp.
|
45
|
+
def self.generate_timestamp()
|
46
|
+
return Time.now.to_i.to_s
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Returns a nonce suitable for use as an <code>'oauth_nonce'</code>
|
51
|
+
# value.
|
52
|
+
#
|
53
|
+
# @return [String] A random nonce.
|
54
|
+
def self.generate_nonce()
|
55
|
+
return SecureRandom.random_bytes(16).unpack('H*').join('')
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Processes an options <code>Hash</code> to find a credential key value.
|
60
|
+
# Allows for greater flexibility in configuration.
|
61
|
+
#
|
62
|
+
# @param [Symbol] credential_type
|
63
|
+
# One of <code>:client</code>, <code>:temporary</code>,
|
64
|
+
# <code>:token</code>, <code>:consumer</code>, <code>:request</code>,
|
65
|
+
# or <code>:access</code>.
|
66
|
+
#
|
67
|
+
# @return [String] The credential key value.
|
68
|
+
def self.extract_credential_key_option(credential_type, options)
|
69
|
+
credential_key_symbol =
|
70
|
+
("#{credential_type}_credential_key").to_sym
|
71
|
+
credential_symbol =
|
72
|
+
("#{credential_type}_credential").to_sym
|
73
|
+
if options[credential_key_symbol]
|
74
|
+
credential_key = options[credential_key_symbol]
|
75
|
+
elsif options[credential_symbol]
|
76
|
+
require 'signet/oauth_1/credential'
|
77
|
+
if !options[credential_symbol].respond_to?(:key)
|
78
|
+
raise TypeError,
|
79
|
+
"Expected Signet::OAuth1::Credential, " +
|
80
|
+
"got #{options[credential_symbol].class}."
|
81
|
+
end
|
82
|
+
credential_key = options[credential_symbol].key
|
83
|
+
elsif options[:client]
|
84
|
+
require 'signet/oauth_1/client'
|
85
|
+
if !options[:client].kind_of?(::Signet::OAuth1::Client)
|
86
|
+
raise TypeError,
|
87
|
+
"Expected Signet::OAuth1::Client, got #{options[:client].class}."
|
88
|
+
end
|
89
|
+
credential_key = options[:client].send(credential_key_symbol)
|
90
|
+
else
|
91
|
+
credential_key = nil
|
92
|
+
end
|
93
|
+
if credential_key != nil && !credential_key.kind_of?(String)
|
94
|
+
raise TypeError,
|
95
|
+
"Expected String, got #{credential_key.class}."
|
96
|
+
end
|
97
|
+
return credential_key
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Processes an options <code>Hash</code> to find a credential secret value.
|
102
|
+
# Allows for greater flexibility in configuration.
|
103
|
+
#
|
104
|
+
# @param [Symbol] credential_type
|
105
|
+
# One of <code>:client</code>, <code>:temporary</code>,
|
106
|
+
# <code>:token</code>, <code>:consumer</code>, <code>:request</code>,
|
107
|
+
# or <code>:access</code>.
|
108
|
+
#
|
109
|
+
# @return [String] The credential secret value.
|
110
|
+
def self.extract_credential_secret_option(credential_type, options)
|
111
|
+
credential_secret_symbol =
|
112
|
+
("#{credential_type}_credential_secret").to_sym
|
113
|
+
credential_symbol =
|
114
|
+
("#{credential_type}_credential").to_sym
|
115
|
+
if options[credential_secret_symbol]
|
116
|
+
credential_secret = options[credential_secret_symbol]
|
117
|
+
elsif options[credential_symbol]
|
118
|
+
require 'signet/oauth_1/credential'
|
119
|
+
if !options[credential_symbol].respond_to?(:secret)
|
120
|
+
raise TypeError,
|
121
|
+
"Expected Signet::OAuth1::Credential, " +
|
122
|
+
"got #{options[credential_symbol].class}."
|
123
|
+
end
|
124
|
+
credential_secret = options[credential_symbol].secret
|
125
|
+
elsif options[:client]
|
126
|
+
require 'signet/oauth_1/client'
|
127
|
+
if !options[:client].kind_of?(::Signet::OAuth1::Client)
|
128
|
+
raise TypeError,
|
129
|
+
"Expected Signet::OAuth1::Client, got #{options[:client].class}."
|
130
|
+
end
|
131
|
+
credential_secret = options[:client].send(credential_secret_symbol)
|
132
|
+
else
|
133
|
+
credential_secret = nil
|
134
|
+
end
|
135
|
+
if credential_secret != nil && !credential_secret.kind_of?(String)
|
136
|
+
raise TypeError,
|
137
|
+
"Expected String, got #{credential_secret.class}."
|
138
|
+
end
|
139
|
+
return credential_secret
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Normalizes a set of OAuth parameters according to the algorithm given
|
144
|
+
# in RFC 5849. Sorts key/value pairs lexically by byte order, first by
|
145
|
+
# key, then by value, joins key/value pairs with the '=' character, then
|
146
|
+
# joins the entire parameter list with '&' characters.
|
147
|
+
#
|
148
|
+
# @param [Enumerable] parameters The OAuth parameter list.
|
149
|
+
#
|
150
|
+
# @return [String] The normalized parameter list.
|
151
|
+
def self.normalize_parameters(parameters)
|
152
|
+
if !parameters.kind_of?(Enumerable)
|
153
|
+
raise TypeError, "Expected Enumerable, got #{parameters.class}."
|
154
|
+
end
|
155
|
+
parameter_list = parameters.map do |k, v|
|
156
|
+
next if k == "oauth_signature"
|
157
|
+
# This is probably the wrong place to try to exclude the realm
|
158
|
+
"#{self.encode(k)}=#{self.encode(v)}"
|
159
|
+
end
|
160
|
+
return parameter_list.compact.sort.join("&")
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Generates a signature base string according to the algorithm given in
|
165
|
+
# RFC 5849. Joins the method, URI, and normalized parameter string with
|
166
|
+
# '&' characters.
|
167
|
+
#
|
168
|
+
# @param [String] method The HTTP method.
|
169
|
+
# @param [Addressable::URI, String, #to_str] The URI.
|
170
|
+
# @param [Enumerable] parameters The OAuth parameter list.
|
171
|
+
#
|
172
|
+
# @return [String] The signature base string.
|
173
|
+
def self.generate_base_string(method, uri, parameters)
|
174
|
+
if !parameters.kind_of?(Enumerable)
|
175
|
+
raise TypeError, "Expected Enumerable, got #{parameters.class}."
|
176
|
+
end
|
177
|
+
method = method.to_s.upcase
|
178
|
+
uri = Addressable::URI.parse(uri).normalize
|
179
|
+
uri_parameters = uri.query_values.to_a
|
180
|
+
uri = uri.omit(:query, :fragment).to_s
|
181
|
+
merged_parameters =
|
182
|
+
uri_parameters.concat(parameters.map { |k, v| [k, v] })
|
183
|
+
parameter_string = self.normalize_parameters(merged_parameters)
|
184
|
+
return [
|
185
|
+
self.encode(method),
|
186
|
+
self.encode(uri),
|
187
|
+
self.encode(parameter_string)
|
188
|
+
].join('&')
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Generates an <code>Authorization</code> header from a parameter list
|
193
|
+
# according to the rules given in RFC 5849.
|
194
|
+
#
|
195
|
+
# @param [Enumerable] parameters The OAuth parameter list.
|
196
|
+
# @param [String] realm
|
197
|
+
# The <code>Authorization</code> realm. See RFC 2617.
|
198
|
+
#
|
199
|
+
# @return [String] The <code>Authorization</code> header.
|
200
|
+
def self.generate_authorization_header(parameters, realm=nil)
|
201
|
+
if !parameters.kind_of?(Enumerable) || parameters.kind_of?(String)
|
202
|
+
raise TypeError, "Expected Enumerable, got #{parameters.class}."
|
203
|
+
end
|
204
|
+
parameter_list = parameters.map do |k, v|
|
205
|
+
if k == 'realm'
|
206
|
+
raise ArgumentError,
|
207
|
+
'The "realm" parameter must be specified as a separate argument.'
|
208
|
+
end
|
209
|
+
"#{self.encode(k)}=\"#{self.encode(v)}\""
|
210
|
+
end
|
211
|
+
if realm
|
212
|
+
realm = realm.gsub('"', '\"')
|
213
|
+
parameter_list.unshift("realm=\"#{realm}\"")
|
214
|
+
end
|
215
|
+
return 'OAuth ' + parameter_list.join(", ")
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# Parses an <code>Authorization</code> header into its component
|
220
|
+
# parameters. Parameter keys and values are decoded according to the
|
221
|
+
# rules given in RFC 5849.
|
222
|
+
def self.parse_authorization_header(header)
|
223
|
+
if !header.kind_of?(String)
|
224
|
+
raise TypeError, "Expected String, got #{header.class}."
|
225
|
+
end
|
226
|
+
unless header[0...6] == 'OAuth '
|
227
|
+
raise ArgumentError,
|
228
|
+
'Parsing non-OAuth Authorization headers is out of scope.'
|
229
|
+
end
|
230
|
+
header = header.gsub(/^OAuth /, '')
|
231
|
+
return header.split(/,\s*/).inject([]) do |accu, pair|
|
232
|
+
k = pair[/^(.*?)=\"[^\"]*\"/, 1]
|
233
|
+
v = pair[/^.*?=\"([^\"]*)\"/, 1]
|
234
|
+
if k != 'realm'
|
235
|
+
k = self.unencode(k)
|
236
|
+
v = self.unencode(v)
|
237
|
+
else
|
238
|
+
v = v.gsub('\"', '"')
|
239
|
+
end
|
240
|
+
accu << [k, v]
|
241
|
+
accu
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
##
|
246
|
+
# Parses an <code>application/x-www-form-urlencoded</code> HTTP response
|
247
|
+
# body into an OAuth key/secret pair.
|
248
|
+
#
|
249
|
+
# @param [String] body The response body.
|
250
|
+
#
|
251
|
+
# @return [Signet::OAuth1::Credential] The OAuth credentials.
|
252
|
+
def self.parse_form_encoded_credentials(body)
|
253
|
+
if !body.kind_of?(String)
|
254
|
+
raise TypeError, "Expected String, got #{body.class}."
|
255
|
+
end
|
256
|
+
return Signet::OAuth1::Credential.new(
|
257
|
+
Addressable::URI.form_unencode(body)
|
258
|
+
)
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Generates an OAuth signature using the signature method indicated in the
|
263
|
+
# parameter list. Unsupported signature methods will result in a
|
264
|
+
# <code>NotImplementedError</code> exception being raised.
|
265
|
+
#
|
266
|
+
# @param [String] method The HTTP method.
|
267
|
+
# @param [Addressable::URI, String, #to_str] The URI.
|
268
|
+
# @param [Enumerable] parameters The OAuth parameter list.
|
269
|
+
# @param [String] client_credential_secret The client credential secret.
|
270
|
+
# @param [String] token_credential_secret
|
271
|
+
# The token credential secret. Omitted when unavailable.
|
272
|
+
#
|
273
|
+
# @return [String] The signature.
|
274
|
+
def self.sign_parameters(method, uri, parameters,
|
275
|
+
client_credential_secret, token_credential_secret=nil)
|
276
|
+
# Technically, the token_credential_secret parameter here may actually
|
277
|
+
# be a temporary credential secret when obtaining a token credential
|
278
|
+
# for the first time
|
279
|
+
base_string = self.generate_base_string(method, uri, parameters)
|
280
|
+
signature_method = Hash[parameters]['oauth_signature_method']
|
281
|
+
case signature_method
|
282
|
+
when 'HMAC-SHA1'
|
283
|
+
require 'signet/oauth_1/signature_methods/hmac_sha1'
|
284
|
+
return Signet::OAuth1::HMACSHA1.generate_signature(
|
285
|
+
base_string, client_credential_secret, token_credential_secret
|
286
|
+
)
|
287
|
+
else
|
288
|
+
raise NotImplementedError,
|
289
|
+
"Unsupported signature method: #{signature_method}"
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
##
|
294
|
+
# Generates an OAuth parameter list to be used when obtaining a set of
|
295
|
+
# temporary credentials.
|
296
|
+
#
|
297
|
+
# @param [Hash] options
|
298
|
+
# The configuration parameters for the request.
|
299
|
+
# - <code>:client_credential_key</code> —
|
300
|
+
# The client credential key.
|
301
|
+
# - <code>:callback</code> —
|
302
|
+
# The OAuth callback. Defaults to {Signet::OAuth1::OUT_OF_BAND}.
|
303
|
+
# - <code>:signature_method</code> —
|
304
|
+
# The signature method. Defaults to <code>'HMAC-SHA1'</code>.
|
305
|
+
# - <code>:additional_parameters</code> —
|
306
|
+
# Non-standard additional parameters.
|
307
|
+
#
|
308
|
+
# @return [Array]
|
309
|
+
# The parameter list as an <code>Array</code> of key/value pairs.
|
310
|
+
def self.unsigned_temporary_credential_parameters(options={})
|
311
|
+
options = {
|
312
|
+
:callback => ::Signet::OAuth1::OUT_OF_BAND,
|
313
|
+
:signature_method => 'HMAC-SHA1',
|
314
|
+
:additional_parameters => []
|
315
|
+
}.merge(options)
|
316
|
+
client_credential_key =
|
317
|
+
self.extract_credential_key_option(:client, options)
|
318
|
+
if client_credential_key == nil
|
319
|
+
raise ArgumentError, "Missing :client_credential_key parameter."
|
320
|
+
end
|
321
|
+
parameters = [
|
322
|
+
["oauth_consumer_key", client_credential_key],
|
323
|
+
["oauth_signature_method", options[:signature_method]],
|
324
|
+
["oauth_timestamp", self.generate_timestamp()],
|
325
|
+
["oauth_nonce", self.generate_nonce()],
|
326
|
+
["oauth_version", "1.0"],
|
327
|
+
["oauth_callback", options[:callback]]
|
328
|
+
]
|
329
|
+
# Works for any Enumerable
|
330
|
+
options[:additional_parameters].each do |key, value|
|
331
|
+
parameters << [key, value]
|
332
|
+
end
|
333
|
+
return parameters
|
334
|
+
end
|
335
|
+
|
336
|
+
##
|
337
|
+
# Appends the optional 'oauth_token' and 'oauth_callback' parameters to
|
338
|
+
# the base authorization URI.
|
339
|
+
#
|
340
|
+
# @param [Addressable::URI, String, #to_str] authorization_uri
|
341
|
+
# The base authorization URI.
|
342
|
+
#
|
343
|
+
# @return [String] The authorization URI to redirect the user to.
|
344
|
+
def self.generate_authorization_uri(authorization_uri, options={})
|
345
|
+
options = {
|
346
|
+
:callback => nil,
|
347
|
+
:additional_parameters => {}
|
348
|
+
}.merge(options)
|
349
|
+
temporary_credential_key =
|
350
|
+
self.extract_credential_key_option(:temporary, options)
|
351
|
+
parsed_uri = Addressable::URI.parse(authorization_uri)
|
352
|
+
query_values = parsed_uri.query_values || {}
|
353
|
+
if options[:additional_parameters]
|
354
|
+
query_values =
|
355
|
+
query_values.merge(Hash[options[:additional_parameters]])
|
356
|
+
end
|
357
|
+
if temporary_credential_key
|
358
|
+
query_values['oauth_token'] = temporary_credential_key
|
359
|
+
end
|
360
|
+
if options[:callback]
|
361
|
+
query_values['oauth_callback'] = options[:callback]
|
362
|
+
end
|
363
|
+
parsed_uri.query_values = query_values
|
364
|
+
return parsed_uri.normalize.to_s
|
365
|
+
end
|
366
|
+
|
367
|
+
##
|
368
|
+
# Generates an OAuth parameter list to be used when obtaining a set of
|
369
|
+
# token credentials.
|
370
|
+
#
|
371
|
+
# @param [Hash] options
|
372
|
+
# The configuration parameters for the request.
|
373
|
+
# - <code>:client_credential_key</code> —
|
374
|
+
# The client credential key.
|
375
|
+
# - <code>:temporary_credential_key</code> —
|
376
|
+
# The temporary credential key.
|
377
|
+
# - <code>:verifier</code> —
|
378
|
+
# The OAuth verifier.
|
379
|
+
# - <code>:signature_method</code> —
|
380
|
+
# The signature method. Defaults to <code>'HMAC-SHA1'</code>.
|
381
|
+
#
|
382
|
+
# @return [Array]
|
383
|
+
# The parameter list as an <code>Array</code> of key/value pairs.
|
384
|
+
def self.unsigned_token_credential_parameters(options={})
|
385
|
+
options = {
|
386
|
+
:signature_method => 'HMAC-SHA1',
|
387
|
+
:verifier => nil
|
388
|
+
}.merge(options)
|
389
|
+
client_credential_key =
|
390
|
+
self.extract_credential_key_option(:client, options)
|
391
|
+
temporary_credential_key =
|
392
|
+
self.extract_credential_key_option(:temporary, options)
|
393
|
+
if client_credential_key == nil
|
394
|
+
raise ArgumentError, "Missing :client_credential_key parameter."
|
395
|
+
end
|
396
|
+
if temporary_credential_key == nil
|
397
|
+
raise ArgumentError, "Missing :temporary_credential_key parameter."
|
398
|
+
end
|
399
|
+
if options[:verifier] == nil
|
400
|
+
raise ArgumentError, "Missing :verifier parameter."
|
401
|
+
end
|
402
|
+
parameters = [
|
403
|
+
["oauth_consumer_key", client_credential_key],
|
404
|
+
["oauth_token", temporary_credential_key],
|
405
|
+
["oauth_signature_method", options[:signature_method]],
|
406
|
+
["oauth_timestamp", self.generate_timestamp()],
|
407
|
+
["oauth_nonce", self.generate_nonce()],
|
408
|
+
["oauth_verifier", options[:verifier]],
|
409
|
+
["oauth_version", "1.0"]
|
410
|
+
]
|
411
|
+
# No additional parameters allowed here
|
412
|
+
return parameters
|
413
|
+
end
|
414
|
+
|
415
|
+
##
|
416
|
+
# Generates an OAuth parameter list to be used when requesting a
|
417
|
+
# protected resource.
|
418
|
+
#
|
419
|
+
# @param [Hash] options
|
420
|
+
# The configuration parameters for the request.
|
421
|
+
# - <code>:client_credential_key</code> —
|
422
|
+
# The client credential key.
|
423
|
+
# - <code>:token_credential_key</code> —
|
424
|
+
# The token credential key.
|
425
|
+
# - <code>:signature_method</code> —
|
426
|
+
# The signature method. Defaults to <code>'HMAC-SHA1'</code>.
|
427
|
+
#
|
428
|
+
# @return [Array]
|
429
|
+
# The parameter list as an <code>Array</code> of key/value pairs.
|
430
|
+
def self.unsigned_resource_parameters(options={})
|
431
|
+
options = {
|
432
|
+
:signature_method => 'HMAC-SHA1'
|
433
|
+
}.merge(options)
|
434
|
+
client_credential_key =
|
435
|
+
self.extract_credential_key_option(:client, options)
|
436
|
+
token_credential_key =
|
437
|
+
self.extract_credential_key_option(:token, options)
|
438
|
+
if client_credential_key == nil
|
439
|
+
raise ArgumentError, "Missing :client_credential_key parameter."
|
440
|
+
end
|
441
|
+
if token_credential_key == nil
|
442
|
+
raise ArgumentError, "Missing :token_credential_key parameter."
|
443
|
+
end
|
444
|
+
parameters = [
|
445
|
+
["oauth_consumer_key", client_credential_key],
|
446
|
+
["oauth_token", token_credential_key],
|
447
|
+
["oauth_signature_method", options[:signature_method]],
|
448
|
+
["oauth_timestamp", self.generate_timestamp()],
|
449
|
+
["oauth_nonce", self.generate_nonce()],
|
450
|
+
["oauth_version", "1.0"]
|
451
|
+
]
|
452
|
+
# No additional parameters allowed here
|
453
|
+
return parameters
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|