ably 0.7.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -7
  3. data/SPEC.md +310 -269
  4. data/lib/ably/auth.rb +177 -127
  5. data/lib/ably/models/presence_message.rb +1 -1
  6. data/lib/ably/models/protocol_message.rb +1 -2
  7. data/lib/ably/models/token_details.rb +101 -0
  8. data/lib/ably/models/token_request.rb +108 -0
  9. data/lib/ably/modules/http_helpers.rb +1 -1
  10. data/lib/ably/realtime.rb +2 -6
  11. data/lib/ably/realtime/channel.rb +14 -8
  12. data/lib/ably/realtime/client.rb +2 -6
  13. data/lib/ably/realtime/connection.rb +4 -2
  14. data/lib/ably/rest.rb +2 -6
  15. data/lib/ably/rest/channel.rb +10 -6
  16. data/lib/ably/rest/client.rb +15 -16
  17. data/lib/ably/rest/presence.rb +12 -10
  18. data/lib/ably/version.rb +1 -1
  19. data/spec/acceptance/realtime/client_spec.rb +15 -15
  20. data/spec/acceptance/realtime/connection_failures_spec.rb +3 -3
  21. data/spec/acceptance/realtime/connection_spec.rb +9 -9
  22. data/spec/acceptance/rest/auth_spec.rb +248 -172
  23. data/spec/acceptance/rest/base_spec.rb +8 -6
  24. data/spec/acceptance/rest/channel_spec.rb +9 -2
  25. data/spec/acceptance/rest/client_spec.rb +21 -21
  26. data/spec/acceptance/rest/presence_spec.rb +12 -5
  27. data/spec/acceptance/rest/stats_spec.rb +4 -4
  28. data/spec/rspec_config.rb +3 -2
  29. data/spec/shared/client_initializer_behaviour.rb +21 -24
  30. data/spec/support/api_helper.rb +3 -3
  31. data/spec/support/test_app.rb +9 -9
  32. data/spec/unit/auth_spec.rb +17 -0
  33. data/spec/unit/models/token_details_spec.rb +111 -0
  34. data/spec/unit/models/token_request_spec.rb +110 -0
  35. data/spec/unit/rest/client_spec.rb +1 -1
  36. metadata +8 -5
  37. data/lib/ably/models/token.rb +0 -74
  38. data/spec/unit/models/token_spec.rb +0 -86
@@ -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: http://docs.ably.io/other/authentication/
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] current_token
15
- # @return [Ably::Models::Token] Current {Ably::Models::Token} issued by this library or one of the provided callbacks used to authenticate requests
16
- # @!attribute [r] token_id
17
- # @return [String] Token ID provided to the {Ably::Client} constructor that is used to authenticate all requests
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 ID and key secret, if present
20
- # @!attribute [r] key_id
21
- # @return [String] Key ID (public part of the API key), if present
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
- attr_reader :options, :current_token
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, &token_request_block)
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
- api_key = auth_options[:key] || auth_options[:api_key] # backwards support for previously used :api_key
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 api_key
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 ID & Secret is needed to authenticate with Ably and obtain a token' unless api_key_present?
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 API key comprising the key ID and key secret in a single string
79
- # @option options [Boolean] :force obtains a new token even if the current token is valid
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 = {}, &token_request_block)
99
- if !options[:force] && current_token
100
- return current_token unless current_token.expired?
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
- api_key = options[:key] || options[:api_key] # backwards support for previously used :api_key
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::Token} which can be used to make authenticated token based requests
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] :key_id key ID for the designated application (defaults to client key_id)
118
- # @option options [String] :key_secret key secret for the designated application used to sign token requests (defaults to client key_secret)
119
- # @option options [String] :client_id client ID identifying this connection to other clients (defaults to client client_id if configured)
120
- # @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.
121
- # @option options [Hash] :auth_headers a set of application-specific headers to be added to any request made to the authUrl
122
- # @option options [Hash] :auth_params a set of application-specific query params to be added to any request made to the authUrl
123
- # @option options [Symbol] :auth_method HTTP method to use with auth_url, must be either `:get` or `:post` (defaults to :get)
124
- # @option options [Integer] :ttl validity time in seconds for the requested {Ably::Models::Token}. Limits may apply, see {http://docs.ably.io/other/authentication/}
125
- # @option options [Hash] :capability canonicalised representation of the resource paths and associated operations
126
- # @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
127
- # @option options [Time] :timestamp the time of the of the request
128
- # @option options [String] :nonce an unquoted, unescaped random string of at least 16 characters
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::Token]
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
- token_options = self.auth_options.merge(options)
149
-
150
- auth_url = token_options.delete(:auth_url)
151
- token_request = if block_given?
152
- yield token_options
153
- elsif default_token_block
154
- default_token_block.call(token_options)
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
- token_request = IdiomaticRubyWrapper(token_request)
162
-
163
- if token_request.has_key?(:issued_at) && token_request.has_key?(:expires)
164
- Ably::Models::Token.new(token_request)
165
- else
166
- response = client.post("/keys/#{token_request.fetch(:id)}/requestToken", token_request.hash, send_auth_header: false, disable_automatic_reauthorise: true)
167
- body = IdiomaticRubyWrapper(response.body)
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] :key_id key ID for the designated application
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::Token}. Limits may apply, see {http://docs.ably.io/other/authentication/}
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
- # @return [Hash]
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
- # # :client_id=>nil,
190
- # # :ttl=>3600,
191
- # # :timestamp=>1410718527,
191
+ # # :clientId=>nil,
192
+ # # :ttl=>3600000,
193
+ # # :timestamp=>1428973674000,
192
194
  # # :capability=>"{\"*\":[\"*\"]}",
193
195
  # # :nonce=>"95e543b88299f6bae83df9b12fbd1ecd",
194
- # # :mac=>"881oZHeFo6oMim7N64y2vFHtSlpQ2gn/uE56a8gUxHw="
195
- # # }
196
+ # # :mac=>"881oZHeFo6oMim7....uE56a8gUxHw="
197
+ # # }
198
+ # #>>
196
199
  def create_token_request(options = {})
197
- token_attributes = %w(id client_id ttl timestamp capability nonce persisted)
200
+ ensure_valid_auth_attributes options
198
201
 
199
- token_options = options.clone
202
+ token_options = options.clone
200
203
 
201
- request_key_id = token_options.delete(:key_id) || key_id
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.to_i
213
+ end
214
+ timestamp = Time.at(timestamp) if timestamp.kind_of?(Integer)
211
215
 
212
216
  token_request = {
213
- id: request_key_id,
214
- clientId: client_id,
215
- ttl: Ably::Models::Token::DEFAULTS[:ttl],
216
- timestamp: timestamp,
217
- capability: Ably::Models::Token::DEFAULTS[:capability],
218
- nonce: SecureRandom.hex
219
- }.merge(token_options.select { |key, val| token_attributes.include?(key.to_s) })
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
- ensure_utf_8 :nonce, token_request[:nonce], allow_nil: true
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
- convert_to_mixed_case_hash(token_request)
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
- "#{key_id}:#{key_secret}" if api_key_present?
236
+ "#{key_name}:#{key_secret}" if api_key_present?
234
237
  end
235
238
 
236
- def key_id
237
- options[:key_id]
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
- token_id || current_token || has_client_id? || token_creatable_externally?
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 token_id
260
- options[:token_id]
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 id and secret and token_id option not provided as token options cannot be determined
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? && !token_id)
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, :default_token_block
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 = (options[:key] || options[:api_key]).to_s.match(/(?<id>[\w_-]+\.[\w_-]+):(?<secret>[\w_-]+)/)
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[:key_id] = api_key_parts[:id].encode(Encoding::UTF_8)
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
- def token_auth_id
327
- if token_id
328
- token_id
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.id
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(token_auth_id)}"
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
- key_id: key_id,
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: token_auth_id
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
- :id,
409
+ :keyName,
362
410
  :ttl,
363
411
  :capability,
364
- :client_id,
412
+ :clientId,
365
413
  :timestamp,
366
414
  :nonce
367
- ).map { |t| "#{t}\n" }.join("")
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
- unless response.body.kind_of?(Hash)
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 token_callback_present?
431
- !!default_token_block
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
- token_callback_present? || token_url_present?
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
- key_id && key_secret
497
+ key_name && key_secret
448
498
  end
449
499
  end
450
500
  end