ably 0.7.6 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -7
- data/SPEC.md +310 -269
- data/lib/ably/auth.rb +177 -127
- data/lib/ably/models/presence_message.rb +1 -1
- data/lib/ably/models/protocol_message.rb +1 -2
- data/lib/ably/models/token_details.rb +101 -0
- data/lib/ably/models/token_request.rb +108 -0
- data/lib/ably/modules/http_helpers.rb +1 -1
- data/lib/ably/realtime.rb +2 -6
- data/lib/ably/realtime/channel.rb +14 -8
- data/lib/ably/realtime/client.rb +2 -6
- data/lib/ably/realtime/connection.rb +4 -2
- data/lib/ably/rest.rb +2 -6
- data/lib/ably/rest/channel.rb +10 -6
- data/lib/ably/rest/client.rb +15 -16
- data/lib/ably/rest/presence.rb +12 -10
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/client_spec.rb +15 -15
- data/spec/acceptance/realtime/connection_failures_spec.rb +3 -3
- data/spec/acceptance/realtime/connection_spec.rb +9 -9
- data/spec/acceptance/rest/auth_spec.rb +248 -172
- data/spec/acceptance/rest/base_spec.rb +8 -6
- data/spec/acceptance/rest/channel_spec.rb +9 -2
- data/spec/acceptance/rest/client_spec.rb +21 -21
- data/spec/acceptance/rest/presence_spec.rb +12 -5
- data/spec/acceptance/rest/stats_spec.rb +4 -4
- data/spec/rspec_config.rb +3 -2
- data/spec/shared/client_initializer_behaviour.rb +21 -24
- data/spec/support/api_helper.rb +3 -3
- data/spec/support/test_app.rb +9 -9
- data/spec/unit/auth_spec.rb +17 -0
- data/spec/unit/models/token_details_spec.rb +111 -0
- data/spec/unit/models/token_request_spec.rb +110 -0
- data/spec/unit/rest/client_spec.rb +1 -1
- metadata +8 -5
- data/lib/ably/models/token.rb +0 -74
- data/spec/unit/models/token_spec.rb +0 -86
data/lib/ably/auth.rb
CHANGED
@@ -5,20 +5,20 @@ require 'securerandom'
|
|
5
5
|
require 'ably/rest/middleware/external_exceptions'
|
6
6
|
|
7
7
|
module Ably
|
8
|
-
# Auth is responsible for authentication with {https://ably.io Ably} using basic or token authentication
|
8
|
+
# Auth is responsible for authentication with {https://www.ably.io Ably} using basic or token authentication
|
9
9
|
#
|
10
|
-
# Find out more about Ably authentication at:
|
10
|
+
# Find out more about Ably authentication at: https://www.ably.io/documentation/general/authentication/
|
11
11
|
#
|
12
12
|
# @!attribute [r] client_id
|
13
13
|
# @return [String] The provided client ID, used for identifying this client for presence purposes
|
14
|
-
# @!attribute [r]
|
15
|
-
# @return [Ably::Models::
|
16
|
-
# @!attribute [r]
|
17
|
-
# @return [String] Token
|
14
|
+
# @!attribute [r] current_token_details
|
15
|
+
# @return [Ably::Models::TokenDetails] Current {Ably::Models::TokenDetails} issued by this library or one of the provided callbacks used to authenticate requests
|
16
|
+
# @!attribute [r] token
|
17
|
+
# @return [String] Token string provided to the {Ably::Client} constructor that is used to authenticate all requests
|
18
18
|
# @!attribute [r] key
|
19
|
-
# @return [String] Complete API key containing both the key
|
20
|
-
# @!attribute [r]
|
21
|
-
# @return [String] Key
|
19
|
+
# @return [String] Complete API key containing both the key name and key secret, if present
|
20
|
+
# @!attribute [r] key_name
|
21
|
+
# @return [String] Key name (public part of the API key), if present
|
22
22
|
# @!attribute [r] key_secret
|
23
23
|
# @return [String] Key secret (private secure part of the API key), if present
|
24
24
|
# @!attribute [r] options
|
@@ -28,7 +28,13 @@ module Ably
|
|
28
28
|
include Ably::Modules::Conversions
|
29
29
|
include Ably::Modules::HttpHelpers
|
30
30
|
|
31
|
-
|
31
|
+
# Default capability Hash object and TTL in seconds for issued tokens
|
32
|
+
TOKEN_DEFAULTS = {
|
33
|
+
capability: { '*' => ['*'] },
|
34
|
+
ttl: 60 * 60 # 1 hour in seconds
|
35
|
+
}
|
36
|
+
|
37
|
+
attr_reader :options, :current_token_details
|
32
38
|
alias_method :auth_options, :options
|
33
39
|
|
34
40
|
# Creates an Auth object
|
@@ -36,33 +42,31 @@ module Ably
|
|
36
42
|
# @param [Ably::Rest::Client] client {Ably::Rest::Client} this Auth object uses
|
37
43
|
# @param [Hash] options (see Ably::Rest::Client#initialize)
|
38
44
|
# @option (see Ably::Rest::Client#initialize)
|
39
|
-
# @yield (see Ably::Rest::Client#initialize)
|
40
45
|
#
|
41
|
-
def initialize(client, options
|
46
|
+
def initialize(client, options)
|
47
|
+
ensure_valid_auth_attributes options
|
48
|
+
|
42
49
|
auth_options = options.dup
|
43
50
|
|
44
51
|
@client = client
|
45
52
|
@options = auth_options
|
46
|
-
@default_token_block = token_request_block if block_given?
|
47
53
|
|
48
54
|
unless auth_options.kind_of?(Hash)
|
49
55
|
raise ArgumentError, 'Expected auth_options to be a Hash'
|
50
56
|
end
|
51
57
|
|
52
|
-
|
53
|
-
|
54
|
-
if api_key && (auth_options[:key_secret] || auth_options[:key_id])
|
55
|
-
raise ArgumentError, 'key and key_id or key_secret are mutually exclusive. Provider either a key or key_id & key_secret'
|
58
|
+
if auth_options[:key] && (auth_options[:key_secret] || auth_options[:key_name])
|
59
|
+
raise ArgumentError, 'key and key_name or key_secret are mutually exclusive. Provider either a key or key_name & key_secret'
|
56
60
|
end
|
57
61
|
|
58
|
-
split_api_key_into_key_and_secret! auth_options if
|
62
|
+
split_api_key_into_key_and_secret! auth_options if auth_options[:key]
|
59
63
|
|
60
64
|
if using_basic_auth? && !api_key_present?
|
61
65
|
raise ArgumentError, 'key is missing. Either an API key, token, or token auth method must be provided'
|
62
66
|
end
|
63
67
|
|
64
68
|
if has_client_id?
|
65
|
-
raise ArgumentError, 'client_id cannot be provided without a complete API key. Key
|
69
|
+
raise ArgumentError, 'client_id cannot be provided without a complete API key. Key name & Secret is needed to authenticate with Ably and obtain a token' unless api_key_present?
|
66
70
|
ensure_utf_8 :client_id, client_id
|
67
71
|
end
|
68
72
|
|
@@ -75,12 +79,8 @@ module Ably
|
|
75
79
|
#
|
76
80
|
# @param [Hash] options the options for the token request
|
77
81
|
# @option options (see #request_token)
|
78
|
-
# @option options [String] :key
|
79
|
-
# @option options [Boolean] :force
|
80
|
-
#
|
81
|
-
# @yield (see #request_token)
|
82
|
-
# @yieldparam [Hash] options options passed to {#authorise} will be in turn sent to the block in this argument
|
83
|
-
# @yieldreturn (see #request_token)
|
82
|
+
# @option options [String] :key API key comprising the key name and key secret in a single string
|
83
|
+
# @option options [Boolean] :force obtains a new token even if the current token is valid
|
84
84
|
#
|
85
85
|
# @return (see #request_token)
|
86
86
|
#
|
@@ -95,43 +95,38 @@ module Ably
|
|
95
95
|
# token_request
|
96
96
|
# end
|
97
97
|
#
|
98
|
-
def authorise(options = {}
|
99
|
-
|
100
|
-
|
98
|
+
def authorise(options = {})
|
99
|
+
ensure_valid_auth_attributes options
|
100
|
+
|
101
|
+
if current_token_details && !options[:force]
|
102
|
+
return current_token_details unless current_token_details.expired?
|
101
103
|
end
|
102
104
|
|
103
105
|
options = options.clone
|
106
|
+
split_api_key_into_key_and_secret! options if options[:key]
|
107
|
+
@options = @options.merge(options) # update default options
|
104
108
|
|
105
|
-
|
106
|
-
split_api_key_into_key_and_secret! options if api_key
|
107
|
-
|
108
|
-
@options = @options.merge(options)
|
109
|
-
@default_token_block = token_request_block if block_given?
|
110
|
-
|
111
|
-
@current_token = request_token(options, &token_request_block)
|
109
|
+
@current_token_details = request_token(options)
|
112
110
|
end
|
113
111
|
|
114
|
-
# Request a {Ably::Models::
|
112
|
+
# Request a {Ably::Models::TokenDetails} which can be used to make authenticated token based requests
|
115
113
|
#
|
116
114
|
# @param [Hash] options the options for the token request
|
117
|
-
# @option options [String] :
|
118
|
-
# @option options [String] :
|
119
|
-
# @option options [String] :
|
120
|
-
# @option options [
|
121
|
-
# @option options [Hash] :
|
122
|
-
# @option options [
|
123
|
-
# @option options [
|
124
|
-
#
|
125
|
-
# @option options [
|
126
|
-
# @option options [
|
127
|
-
# @option options [
|
128
|
-
# @option options [
|
129
|
-
#
|
130
|
-
# @yield [options] (optional) if a token request block is passed to this method, then this block will be called whenever a new token is required
|
131
|
-
# @yieldparam [Hash] options options passed to {#request_token} will be in turn sent to the block in this argument
|
132
|
-
# @yieldreturn [Hash] expects a valid token request object, see {#create_token_request}
|
115
|
+
# @option options [String] :key complete API key for the designated application
|
116
|
+
# @option options [String] :client_id client ID identifying this connection to other clients (defaults to client client_id if configured)
|
117
|
+
# @option options [String] :auth_url a URL to be used to GET or POST a set of token request params, to obtain a signed token request.
|
118
|
+
# @option options [Hash] :auth_headers a set of application-specific headers to be added to any request made to the authUrl
|
119
|
+
# @option options [Hash] :auth_params a set of application-specific query params to be added to any request made to the authUrl
|
120
|
+
# @option options [Symbol] :auth_method HTTP method to use with auth_url, must be either `:get` or `:post` (defaults to :get)
|
121
|
+
# @option options [Proc] :auth_callback this Proc / block will be called with the {#auth_options Auth#auth_options Hash} as the first argument whenever a new token is required.
|
122
|
+
# The Proc should return a token string, {Ably::Models::TokenDetails} or JSON equivalent, {Ably::Models::TokenRequest} or JSON equivalent
|
123
|
+
# @option options [Integer] :ttl validity time in seconds for the requested {Ably::Models::TokenDetails}. Limits may apply, see {https://www.ably.io/documentation/other/authentication}
|
124
|
+
# @option options [Hash] :capability canonicalised representation of the resource paths and associated operations
|
125
|
+
# @option options [Boolean] :query_time when true will query the {https://www.ably.io Ably} system for the current time instead of using the local time
|
126
|
+
# @option options [Time] :timestamp the time of the of the request
|
127
|
+
# @option options [String] :nonce an unquoted, unescaped random string of at least 16 characters
|
133
128
|
#
|
134
|
-
# @return [Ably::Models::
|
129
|
+
# @return [Ably::Models::TokenDetails]
|
135
130
|
#
|
136
131
|
# @example
|
137
132
|
# # simple token request using basic auth
|
@@ -145,96 +140,104 @@ module Ably
|
|
145
140
|
# end
|
146
141
|
#
|
147
142
|
def request_token(options = {})
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
elsif auth_url
|
143
|
+
ensure_valid_auth_attributes options
|
144
|
+
|
145
|
+
token_options = auth_options.merge(options)
|
146
|
+
|
147
|
+
token_request = if auth_callback = token_options.delete(:auth_callback)
|
148
|
+
auth_callback.call(token_options)
|
149
|
+
elsif auth_url = token_options.delete(:auth_url)
|
156
150
|
token_request_from_auth_url(auth_url, token_options)
|
157
151
|
else
|
158
152
|
create_token_request(token_options)
|
159
153
|
end
|
160
154
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
Ably::Models::Token.new(body.fetch(:access_token))
|
155
|
+
case token_request
|
156
|
+
when Ably::Models::TokenDetails
|
157
|
+
return token_request
|
158
|
+
when Hash
|
159
|
+
return Ably::Models::TokenDetails.new(token_request) if IdiomaticRubyWrapper(token_request).has_key?(:issued)
|
160
|
+
when String
|
161
|
+
return Ably::Models::TokenDetails.new(token: token_request)
|
169
162
|
end
|
163
|
+
|
164
|
+
token_request = Ably::Models::TokenRequest(token_request)
|
165
|
+
|
166
|
+
response = client.post("/keys/#{token_request.key_name}/requestToken",
|
167
|
+
token_request.hash, send_auth_header: false,
|
168
|
+
disable_automatic_reauthorise: true)
|
169
|
+
|
170
|
+
Ably::Models::TokenDetails.new(response.body)
|
170
171
|
end
|
171
172
|
|
172
173
|
# Creates and signs a token request that can then subsequently be used by any client to request a token
|
173
174
|
#
|
174
175
|
# @param [Hash] options the options for the token request
|
175
|
-
# @option options [String] :
|
176
|
-
# @option options [String] :key_secret key secret for the designated application used to sign token requests (defaults to client key_secret)
|
176
|
+
# @option options [String] :key complete API key for the designated application
|
177
177
|
# @option options [String] :client_id client ID identifying this connection to other clients
|
178
|
-
# @option options [Integer] :ttl validity time in seconds for the requested {Ably::Models::
|
178
|
+
# @option options [Integer] :ttl validity time in seconds for the requested {Ably::Models::TokenDetails}. Limits may apply, see {https://www.ably.io/documentation/other/authentication}
|
179
179
|
# @option options [Hash] :capability canonicalised representation of the resource paths and associated operations
|
180
|
-
# @option options [Boolean] :query_time when true will query the {https://ably.io Ably} system for the current time instead of using the local time
|
180
|
+
# @option options [Boolean] :query_time when true will query the {https://www.ably.io Ably} system for the current time instead of using the local time
|
181
181
|
# @option options [Time] :timestamp the time of the of the request
|
182
182
|
# @option options [String] :nonce an unquoted, unescaped random string of at least 16 characters
|
183
|
-
#
|
183
|
+
#
|
184
|
+
# @return [Models::TokenRequest]
|
184
185
|
#
|
185
186
|
# @example
|
186
187
|
# client.auth.create_token_request(id: 'asd.asd', ttl: 3600)
|
187
|
-
#
|
188
|
+
# #<Ably::Models::TokenRequest:0x007fd5d919df78
|
189
|
+
# # @hash={
|
188
190
|
# # :id=>"asds.adsa",
|
189
|
-
# # :
|
190
|
-
# # :ttl=>
|
191
|
-
# # :timestamp=>
|
191
|
+
# # :clientId=>nil,
|
192
|
+
# # :ttl=>3600000,
|
193
|
+
# # :timestamp=>1428973674000,
|
192
194
|
# # :capability=>"{\"*\":[\"*\"]}",
|
193
195
|
# # :nonce=>"95e543b88299f6bae83df9b12fbd1ecd",
|
194
|
-
# # :mac=>"
|
195
|
-
# #
|
196
|
+
# # :mac=>"881oZHeFo6oMim7....uE56a8gUxHw="
|
197
|
+
# # }
|
198
|
+
# #>>
|
196
199
|
def create_token_request(options = {})
|
197
|
-
|
200
|
+
ensure_valid_auth_attributes options
|
198
201
|
|
199
|
-
token_options
|
202
|
+
token_options = options.clone
|
200
203
|
|
201
|
-
|
204
|
+
split_api_key_into_key_and_secret! token_options if token_options[:key]
|
205
|
+
request_key_name = token_options.delete(:key_name) || key_name
|
202
206
|
request_key_secret = token_options.delete(:key_secret) || key_secret
|
203
|
-
|
204
|
-
raise Ably::Exceptions::TokenRequestError, 'Key ID and Key Secret are required to generate a new token request' unless request_key_id && request_key_secret
|
207
|
+
raise Ably::Exceptions::TokenRequestError, 'Key Name and Key Secret are required to generate a new token request' unless request_key_name && request_key_secret
|
205
208
|
|
206
209
|
timestamp = if token_options[:query_time]
|
207
210
|
client.time
|
208
211
|
else
|
209
212
|
token_options.delete(:timestamp) || Time.now
|
210
|
-
end
|
213
|
+
end
|
214
|
+
timestamp = Time.at(timestamp) if timestamp.kind_of?(Integer)
|
211
215
|
|
212
216
|
token_request = {
|
213
|
-
|
214
|
-
clientId: client_id,
|
215
|
-
ttl:
|
216
|
-
timestamp: timestamp,
|
217
|
-
capability:
|
218
|
-
nonce: SecureRandom.hex
|
219
|
-
}
|
220
|
-
|
221
|
-
if token_request[:capability].is_a?(Hash)
|
222
|
-
token_request[:capability] = token_request[:capability].to_json
|
223
|
-
end
|
217
|
+
keyName: token_options[:key_name] || request_key_name,
|
218
|
+
clientId: token_options[:client_id] || client_id,
|
219
|
+
ttl: ((token_options[:ttl] || TOKEN_DEFAULTS.fetch(:ttl)) * 1000).to_i,
|
220
|
+
timestamp: (timestamp.to_f * 1000).round,
|
221
|
+
capability: token_options[:capability] || TOKEN_DEFAULTS.fetch(:capability),
|
222
|
+
nonce: token_options[:nonce] || SecureRandom.hex
|
223
|
+
}
|
224
224
|
|
225
|
-
|
225
|
+
token_request[:capability] = JSON.dump(token_request[:capability]) if token_request[:capability].is_a?(Hash)
|
226
226
|
|
227
227
|
token_request[:mac] = sign_params(token_request, request_key_secret)
|
228
228
|
|
229
|
-
|
229
|
+
# Undocumented feature to request a persisted token
|
230
|
+
token_request[:persisted] = options[:persisted] if options[:persisted]
|
231
|
+
|
232
|
+
Models::TokenRequest.new(token_request)
|
230
233
|
end
|
231
234
|
|
232
235
|
def key
|
233
|
-
"#{
|
236
|
+
"#{key_name}:#{key_secret}" if api_key_present?
|
234
237
|
end
|
235
238
|
|
236
|
-
def
|
237
|
-
options[:
|
239
|
+
def key_name
|
240
|
+
options[:key_name]
|
238
241
|
end
|
239
242
|
|
240
243
|
def key_secret
|
@@ -249,15 +252,21 @@ module Ably
|
|
249
252
|
# True when Token Auth is being used to authenticate with Ably
|
250
253
|
def using_token_auth?
|
251
254
|
return options[:use_token_auth] if options.has_key?(:use_token_auth)
|
252
|
-
|
255
|
+
token || current_token_details || has_client_id? || token_creatable_externally?
|
253
256
|
end
|
254
257
|
|
255
258
|
def client_id
|
256
259
|
options[:client_id]
|
257
260
|
end
|
258
261
|
|
259
|
-
def
|
260
|
-
options[:
|
262
|
+
def token
|
263
|
+
token_object = options[:token] || options[:token_details]
|
264
|
+
|
265
|
+
if token_object.kind_of?(Ably::Models::TokenDetails)
|
266
|
+
token_object.token
|
267
|
+
else
|
268
|
+
token_object
|
269
|
+
end
|
261
270
|
end
|
262
271
|
|
263
272
|
# Auth header string used in HTTP requests to Ably
|
@@ -285,13 +294,13 @@ module Ably
|
|
285
294
|
# True if prerequisites for creating a new token request are present
|
286
295
|
#
|
287
296
|
# One of the following criterion must be met:
|
288
|
-
# * Valid key
|
297
|
+
# * Valid API key and token option not provided as token options cannot be determined
|
289
298
|
# * Authentication callback for new token requests
|
290
299
|
# * Authentication URL for new token requests
|
291
300
|
#
|
292
301
|
# @return [Boolean]
|
293
302
|
def token_renewable?
|
294
|
-
token_creatable_externally? || (api_key_present? && !
|
303
|
+
token_creatable_externally? || (api_key_present? && !token)
|
295
304
|
end
|
296
305
|
|
297
306
|
# Returns false when attempting to send an API Key over a non-secure connection
|
@@ -303,7 +312,45 @@ module Ably
|
|
303
312
|
end
|
304
313
|
|
305
314
|
private
|
306
|
-
attr_reader :client
|
315
|
+
attr_reader :client
|
316
|
+
|
317
|
+
def ensure_valid_auth_attributes(attributes)
|
318
|
+
if attributes[:timestamp]
|
319
|
+
unless attributes[:timestamp].kind_of?(Time) || attributes[:timestamp].kind_of?(Numeric)
|
320
|
+
raise ArgumentError, ':timestamp must be a Time or positive Integer value of seconds since epoch'
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
if attributes[:ttl]
|
325
|
+
unless attributes[:ttl].kind_of?(Numeric) && attributes[:ttl].to_f > 0
|
326
|
+
raise ArgumentError, ':ttl must be a positive Numeric value representing time to live in seconds'
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
if attributes[:auth_headers]
|
331
|
+
unless attributes[:auth_headers].kind_of?(Hash)
|
332
|
+
raise ArgumentError, ':auth_headers must be a valid Hash'
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
if attributes[:auth_params]
|
337
|
+
unless attributes[:auth_params].kind_of?(Hash)
|
338
|
+
raise ArgumentError, ':auth_params must be a valid Hash'
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
if attributes[:auth_method]
|
343
|
+
unless %(get post).include?(attributes[:auth_method].to_s)
|
344
|
+
raise ArgumentError, ':auth_method must be either :get or :post'
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
if attributes[:auth_callback]
|
349
|
+
unless attributes[:auth_callback].respond_to?(:call)
|
350
|
+
raise ArgumentError, ':auth_callback must be a Proc'
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
307
354
|
|
308
355
|
def ensure_api_key_sent_over_secure_connection
|
309
356
|
raise Ably::Exceptions::InsecureRequestError, 'Cannot use Basic Auth over non-TLS connections' unless authentication_security_requirements_met?
|
@@ -316,40 +363,41 @@ module Ably
|
|
316
363
|
end
|
317
364
|
|
318
365
|
def split_api_key_into_key_and_secret!(options)
|
319
|
-
api_key_parts =
|
366
|
+
api_key_parts = options[:key].to_s.match(/(?<name>[\w_-]+\.[\w_-]+):(?<secret>[\w_-]+)/)
|
320
367
|
raise ArgumentError, 'key is invalid' unless api_key_parts
|
321
368
|
|
322
|
-
options[:
|
369
|
+
options[:key_name] = api_key_parts[:name].encode(Encoding::UTF_8)
|
323
370
|
options[:key_secret] = api_key_parts[:secret].encode(Encoding::UTF_8)
|
371
|
+
|
372
|
+
options.delete :key
|
324
373
|
end
|
325
374
|
|
326
|
-
|
327
|
-
|
328
|
-
|
375
|
+
# Returns the current token if it exists or authorises and retrieves a token
|
376
|
+
def token_auth_string
|
377
|
+
if token
|
378
|
+
token
|
329
379
|
else
|
330
|
-
authorise.
|
380
|
+
authorise.token
|
331
381
|
end
|
332
382
|
end
|
333
383
|
|
334
384
|
# Token Auth HTTP Authorization header value
|
335
385
|
def token_auth_header
|
336
|
-
"Bearer #{encode64(
|
386
|
+
"Bearer #{encode64(token_auth_string)}"
|
337
387
|
end
|
338
388
|
|
339
389
|
# Basic Auth params to authenticate the Realtime connection
|
340
390
|
def basic_auth_params
|
341
391
|
ensure_api_key_sent_over_secure_connection
|
342
|
-
# TODO: Change to key_secret when API is updated
|
343
392
|
{
|
344
|
-
|
345
|
-
key_value: key_secret
|
393
|
+
key: key
|
346
394
|
}
|
347
395
|
end
|
348
396
|
|
349
397
|
# Token Auth params to authenticate the Realtime connection
|
350
398
|
def token_auth_params
|
351
399
|
{
|
352
|
-
access_token:
|
400
|
+
access_token: token_auth_string
|
353
401
|
}
|
354
402
|
end
|
355
403
|
|
@@ -358,13 +406,15 @@ module Ably
|
|
358
406
|
# @return [Hash]
|
359
407
|
def sign_params(params, secret)
|
360
408
|
text = params.values_at(
|
361
|
-
:
|
409
|
+
:keyName,
|
362
410
|
:ttl,
|
363
411
|
:capability,
|
364
|
-
:
|
412
|
+
:clientId,
|
365
413
|
:timestamp,
|
366
414
|
:nonce
|
367
|
-
).map
|
415
|
+
).map do |val|
|
416
|
+
"#{val}\n"
|
417
|
+
end.join('')
|
368
418
|
|
369
419
|
encode64(
|
370
420
|
OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, secret, text)
|
@@ -385,7 +435,7 @@ module Ably
|
|
385
435
|
request.headers = options[:auth_headers] || {}
|
386
436
|
end
|
387
437
|
|
388
|
-
|
438
|
+
if !response.body.kind_of?(Hash) && response.headers['Content-Type'] != 'text/plain'
|
389
439
|
raise Ably::Exceptions::InvalidResponseBody,
|
390
440
|
"Content Type #{response.headers['Content-Type']} is not supported by this client library"
|
391
441
|
end
|
@@ -427,8 +477,8 @@ module Ably
|
|
427
477
|
end
|
428
478
|
end
|
429
479
|
|
430
|
-
def
|
431
|
-
!!
|
480
|
+
def auth_callback_present?
|
481
|
+
!!options[:auth_callback]
|
432
482
|
end
|
433
483
|
|
434
484
|
def token_url_present?
|
@@ -436,7 +486,7 @@ module Ably
|
|
436
486
|
end
|
437
487
|
|
438
488
|
def token_creatable_externally?
|
439
|
-
|
489
|
+
auth_callback_present? || token_url_present?
|
440
490
|
end
|
441
491
|
|
442
492
|
def has_client_id?
|
@@ -444,7 +494,7 @@ module Ably
|
|
444
494
|
end
|
445
495
|
|
446
496
|
def api_key_present?
|
447
|
-
|
497
|
+
key_name && key_secret
|
448
498
|
end
|
449
499
|
end
|
450
500
|
end
|