spec/acceptance/rest/auth_spec.rb in ably-0.7.6 vs spec/acceptance/rest/auth_spec.rb in ably-0.8.0

- old
+ new

@@ -2,21 +2,21 @@ require 'spec_helper' describe Ably::Auth do include Ably::Modules::Conversions - def hmac_for(token_request, secret) - ruby_named_token_request = Ably::Models::IdiomaticRubyWrapper.new(token_request) + def hmac_for(token_request_attributes, secret) + token_request= Ably::Models::IdiomaticRubyWrapper.new(token_request_attributes) text = [ - :id, + :key_name, :ttl, :capability, :client_id, :timestamp, :nonce - ].map { |key| "#{ruby_named_token_request[key]}\n" }.join("") + ].map { |key| "#{token_request.hash[key]}\n" }.join("") encode64( OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, secret, text) ) end @@ -50,84 +50,118 @@ JSON.dump(token_response) end end it 'has immutable options' do - expect { auth.options['key_id'] = 'new_id' }.to raise_error RuntimeError, /can't modify frozen.*Hash/ + expect { auth.options['key_name'] = 'new_name' }.to raise_error RuntimeError, /can't modify frozen.*Hash/ end describe '#request_token' do let(:ttl) { 30 * 60 } let(:capability) { { :foo => ['publish'] } } - let(:token) do + let(:token_details) do auth.request_token( ttl: ttl, capability: capability ) end - it 'returns a valid requested token in the expected format with valid issued_at and expires_at attributes' do - expect(token.id).to match(/^#{app_id}\.[\w-]+$/) - expect(token.key_id).to match(/^#{key_id}$/) - expect(token.issued_at).to be_within(2).of(Time.now) - expect(token.expires_at).to be_within(2).of(Time.now + ttl) + it 'returns a valid requested token in the expected format with valid issued and expires attributes' do + expect(token_details.token).to match(/^#{app_id}\.[\w-]+$/) + expect(token_details.key_name).to match(/^#{key_name}$/) + expect(token_details.issued).to be_within(2).of(Time.now) + expect(token_details.expires).to be_within(2).of(Time.now + ttl) end %w(client_id capability nonce timestamp ttl).each do |option| context "with option :#{option}", :webmock do - let(:random) { random_int_str } + def coerce_if_time_value(field_name, value, multiply: false) + return value unless %w(timestamp ttl).include?(field_name) + value.to_i * (multiply ? multiply : 1) + end + + let(:random) { coerce_if_time_value(option, random_int_str) } let(:options) { { option.to_sym => random } } - let(:token_response) { { access_token: {} } } + let(:token_response) { {} } let!(:request_token_stub) do - stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken"). + stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken"). with do |request| - request_body_includes(request, protocol, option, random) + request_body_includes(request, protocol, option, coerce_if_time_value(option, random, multiply: 1000)) end.to_return( :status => 201, :body => serialize(token_response, protocol), :headers => { 'Content-Type' => content_type } ) end before { auth.request_token options } - it 'overrides default and uses camelCase notation for all attributes' do + it "overrides default and uses camelCase notation for attributes" do expect(request_token_stub).to have_been_requested end end end - context 'with :key_id & :key_secret options', :webmock do - let(:key_id) { random_str } + context 'with :key option', :webmock do + let(:key_name) { "app.#{random_str}" } let(:key_secret) { random_str } let(:nonce) { random_str } - let(:token_options) { { key_id: key_id, key_secret: key_secret, nonce: nonce, timestamp: Time.now } } + let(:token_options) { { key: "#{key_name}:#{key_secret}", nonce: nonce, timestamp: Time.now } } let(:token_request) { auth.create_token_request(token_options) } let(:mac) do hmac_for(token_request, key_secret) end - let(:token_response) { { access_token: {} } } + let(:token_response) { {} } let!(:request_token_stub) do - stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken"). + stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken"). with do |request| request_body_includes(request, protocol, 'mac', mac) end.to_return( :status => 201, :body => serialize(token_response, protocol), :headers => { 'Content-Type' => content_type }) end - let!(:token) { auth.request_token(token_options) } + let!(:token) { puts token_options; auth.request_token(token_options) } - specify 'key_id is used in request and signing uses key_secret' do + specify 'key_name is used in request and signing uses key_secret' do expect(request_token_stub).to have_been_requested end end + context 'with :key_name & :key_secret options', :webmock do + let(:key_name) { "app.#{random_str}" } + let(:key_secret) { random_str } + let(:nonce) { random_str } + + let(:name_secret_token_options) { { key_name: key_name, key_secret: key_secret, nonce: nonce, timestamp: Time.now } } + let(:token_request) { auth.create_token_request(name_secret_token_options) } + let(:mac) do + hmac_for(token_request, key_secret) + end + + let(:token_response) { {} } + let!(:request_token_stub) do + stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken"). + with do |request| + request_body_includes(request, protocol, 'mac', mac) + end.to_return( + :status => 201, + :body => serialize(token_response, protocol), + :headers => { 'Content-Type' => content_type }) + end + + let!(:token) { auth.request_token(name_secret_token_options); } + + specify 'key_name is used in request and signing uses key_secret' do + expect(request_token_stub).to have_been_requested + end + end + context 'with :query_time option' do let(:options) { { query_time: true } } it 'queries the server for the time' do expect(client).to receive(:time).and_call_original @@ -144,12 +178,12 @@ end end context 'with :auth_url option', :webmock do let(:auth_url) { 'https://www.fictitious.com/get_token' } - let(:auth_url_response) { { id: key_id } } - let(:token_response) { { access_token: { } } } + let(:auth_url_response) { { keyName: key_name }.to_json } + let(:token_response) { {} } let(:query_params) { nil } let(:headers) { nil } let(:auth_method) { :get } let(:options) do { @@ -164,19 +198,20 @@ stub = stub_request(auth_method, auth_url) stub.with(:query => query_params) unless query_params.nil? stub.with(:headers => headers) unless headers.nil? stub.to_return( :status => 201, - :body => auth_url_response.to_json, - :headers => { 'Content-Type' => 'application/json' } + :body => auth_url_response, + :headers => { 'Content-Type' => auth_url_content_type } ) end + let(:auth_url_content_type) { 'application/json' } let!(:request_token_stub) do - stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken"). + stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken"). with do |request| - request_body_includes(request, protocol, 'id', key_id) + request_body_includes(request, protocol, 'key_name', key_name) end.to_return( :status => 201, :body => serialize(token_response, protocol), :headers => { 'Content-Type' => content_type } ) @@ -189,11 +224,11 @@ expect(request_token_stub).to have_been_requested expect(auth_url_request_stub).to have_been_requested end it 'returns a valid token generated from the token request' do - expect(token).to be_a(Ably::Models::Token) + expect(token).to be_a(Ably::Models::TokenDetails) end context 'with :query_params' do let(:query_params) { { 'key' => random_str } } @@ -218,36 +253,52 @@ expect(auth_url_request_stub).to have_been_requested end end end - context 'when response from :auth_url is a token' do - let(:token_id) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' } - let(:issued_at) { Time.now } + context 'when response from :auth_url is a token details object' do + let(:token) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' } + let(:issued) { Time.now } let(:expires) { Time.now + 60} let(:capability) { {'foo'=>['publish']} } + let(:capability_str) { JSON.dump(capability) } let(:auth_url_response) do { - 'id' => token_id, - 'key' => 'J_0Tlg.NxCRig', - 'issued_at' => issued_at.to_i, - 'expires' => expires.to_i, - 'capability'=> capability - } + 'token' => token, + 'key_name' => 'J_0Tlg.NxCRig', + 'issued' => issued.to_i * 1000, + 'expires' => expires.to_i * 1000, + 'capability'=> capability_str + }.to_json end - let!(:token) { auth.request_token(options) } + let!(:token_details) { auth.request_token(options) } - it 'returns a Token created from the token JSON' do + it 'returns TokenDetails created from the token JSON' do expect(request_token_stub).to_not have_been_requested - expect(token.id).to eql(token_id) - expect(token.expires_at).to be_within(1).of(expires) - expect(token.issued_at).to be_within(1).of(issued_at) - expect(token.capability.to_json).to eql(capability.to_json) + expect(token_details).to be_a(Ably::Models::TokenDetails) + expect(token_details.token).to eql(token) + expect(token_details.expires).to be_within(1).of(expires) + expect(token_details.issued).to be_within(1).of(issued) + expect(token_details.capability).to eql(capability) end end + context 'when response from :auth_url is text/plain content type and a token string' do + let(:token) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' } + let(:auth_url_content_type) { 'text/plain' } + let(:auth_url_response) { token } + + let!(:token_details) { auth.request_token(options) } + + it 'returns TokenDetails created from the token JSON' do + expect(request_token_stub).to_not have_been_requested + expect(token_details).to be_a(Ably::Models::TokenDetails) + expect(token_details.token).to eql(token) + end + end + context 'when response is invalid' do context '500' do let!(:auth_url_request_stub) do stub_request(auth_method, auth_url).to_return(:status => 500) end @@ -268,103 +319,139 @@ end end end end - context 'with token_request_block that returns a token request' do - let(:client_id) { random_str } - let(:options) { { client_id: client_id } } - let!(:request_token) do - auth.request_token(options) do |block_options| - @block_called = true - @block_options = block_options - auth.create_token_request(client_id: client_id) + context 'with a Proc for the :auth_callback option' do + context 'that returns a TokenRequest' do + let(:client_id) { random_str } + let(:options) { { client_id: client_id } } + let!(:request_token) do + auth.request_token(options.merge(auth_callback: Proc.new do |block_options| + @block_called = true + @block_options = block_options + auth.create_token_request(client_id: client_id) + end)) end - end - it 'calls the block when authenticating to obtain the request token' do - expect(@block_called).to eql(true) - expect(@block_options).to include(options) - end + it 'calls the Proc when authenticating to obtain the request token' do + expect(@block_called).to eql(true) + expect(@block_options).to include(options) + end - it 'uses the token request from the block when requesting a new token' do - expect(request_token.client_id).to eql(client_id) + it 'uses the token request returned from the callback when requesting a new token' do + expect(request_token.client_id).to eql(client_id) + end end - end - context 'with token_request_block that returns a token' do - let(:client_id) { random_str } - let(:options) { { client_id: client_id } } - let(:token_id) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' } - let(:issued_at) { Time.now } - let(:expires) { Time.now + 60} - let(:capability) { {'foo'=>['publish']} } + context 'that returns a TokenDetails JSON object' do + let(:client_id) { random_str } + let(:options) { { client_id: client_id } } + let(:token) { 'J_0Tlg.D7AVZkdOZW-PqNNGvCSp38' } + let(:issued) { Time.now } + let(:expires) { Time.now + 60} + let(:capability) { {'foo'=>['publish']} } + let(:capability_str) { JSON.dump(capability) } - let!(:request_token) do - auth.request_token(options) do |block_options| - @block_called = true - @block_options = block_options - { - 'id' => token_id, - 'key' => 'J_0Tlg.NxCRig', - 'client_id' => client_id, - 'issued_at' => issued_at.to_i, - 'expires' => expires.to_i, - 'capability'=> capability - } + let!(:token_details) do + auth.request_token(options.merge(auth_callback: Proc.new do |block_options| + @block_called = true + @block_options = block_options + { + 'token' => token, + 'keyName' => 'J_0Tlg.NxCRig', + 'clientId' => client_id, + 'issued' => issued.to_i * 1000, + 'expires' => expires.to_i * 1000, + 'capability'=> capability_str + } + end)) end + + it 'calls the Proc when authenticating to obtain the request token' do + expect(@block_called).to eql(true) + expect(@block_options).to include(options) + end + + it 'uses the token request returned from the callback when requesting a new token' do + expect(token_details).to be_a(Ably::Models::TokenDetails) + expect(token_details.token).to eql(token) + expect(token_details.client_id).to eql(client_id) + expect(token_details.expires).to be_within(1).of(expires) + expect(token_details.issued).to be_within(1).of(issued) + expect(token_details.capability).to eql(capability) + end end - it 'calls the block when authenticating to obtain the request token' do - expect(@block_called).to eql(true) - expect(@block_options).to include(options) + context 'that returns a TokenDetails object' do + let(:client_id) { random_str } + + let!(:token_details) do + auth.request_token(auth_callback: Proc.new do |block_options| + auth.create_token_request({ + client_id: client_id + }) + end) + end + + it 'uses the token request returned from the callback when requesting a new token' do + expect(token_details).to be_a(Ably::Models::TokenDetails) + expect(token_details.client_id).to eql(client_id) + end end - it 'uses the token request from the block when requesting a new token' do - expect(request_token).to be_a(Ably::Models::Token) - expect(request_token.id).to eql(token_id) - expect(request_token.client_id).to eql(client_id) - expect(request_token.expires_at).to be_within(1).of(expires) - expect(request_token.issued_at).to be_within(1).of(issued_at) - expect(request_token.capability.to_json).to eql(capability.to_json) + context 'that returns a Token string' do + let(:second_client) { Ably::Rest::Client.new(key: api_key, environment: environment, protocol: protocol) } + let(:token) { second_client.auth.request_token.token } + + let!(:token_details) do + auth.request_token(auth_callback: Proc.new do |block_options| + token + end) + end + + it 'uses the token request returned from the callback when requesting a new token' do + expect(token_details).to be_a(Ably::Models::TokenDetails) + expect(token_details.token).to eql(token) + end end end context 'persisted option', api_private: true do context 'when set to true', api_private: true do let(:options) { { persisted: true } } - let(:token) { auth.request_token(options) } + let(:token_details) { auth.request_token(options) } it 'returns a token with a short token ID that is used to look up the token details' do - expect(token.id.length).to be < 64 - expect(token.id).to match(/^#{app_id}\.A/) + expect(token_details.token.length).to be < 64 + expect(token_details.token).to match(/^#{app_id}\.A/) end end context 'when omitted', api_private: true do let(:options) { { } } - let(:token) { auth.request_token(options) } + let(:token_details) { auth.request_token(options) } it 'returns a literal token' do - expect(token.id.length).to be > 64 + expect(token_details.token.length).to be > 64 end end end context 'with client_id' do let(:client_id) { random_str } - let(:token) { auth.request_token(client_id: client_id) } + let(:token_details) { auth.request_token(client_id: client_id) } it 'returns a token with the client_id' do - expect(token.client_id).to eql(client_id) + expect(token_details.client_id).to eql(client_id) end end end context 'before #authorise has been called' do - it 'has no current_token' do - expect(auth.current_token).to be_nil + it 'has no current_token_details' do + expect(auth.current_token_details).to be_nil end end describe '#authorise' do context 'when called for the first time since the client has been instantiated' do @@ -376,75 +463,75 @@ expect(auth).to receive(:request_token).with(request_options) auth.authorise request_options end it 'returns a valid token' do - expect(auth.authorise).to be_a(Ably::Models::Token) + expect(auth.authorise).to be_a(Ably::Models::TokenDetails) end it 'issues a new token if option :force => true' do - expect { auth.authorise(force: true) }.to change { auth.current_token } + expect { auth.authorise(force: true) }.to change { auth.current_token_details } end end context 'with previous authorisation' do before do auth.authorise - expect(auth.current_token).to_not be_expired + expect(auth.current_token_details).to_not be_expired end - it 'does not request a token if current_token has not expired' do + it 'does not request a token if current_token_details has not expired' do expect(auth).to_not receive(:request_token) auth.authorise end it 'requests a new token if token is expired' do - allow(auth.current_token).to receive(:expired?).and_return(true) + allow(auth.current_token_details).to receive(:expired?).and_return(true) expect(auth).to receive(:request_token) - expect { auth.authorise }.to change { auth.current_token } + expect { auth.authorise }.to change { auth.current_token_details } end it 'issues a new token if option :force => true' do - expect { auth.authorise(force: true) }.to change { auth.current_token } + expect { auth.authorise(force: true) }.to change { auth.current_token_details } end end - it 'updates the persisted auth options thare are then used for subsequent authorise requests' do + it 'updates the persisted auth options that are then used for subsequent authorise requests' do expect(auth.options[:ttl]).to_not eql(26) auth.authorise(ttl: 26) expect(auth.options[:ttl]).to eql(26) end - context 'with token_request_block' do + context 'with a Proc for the :auth_callback option' do let(:client_id) { random_str } let!(:token) do - auth.authorise do + auth.authorise(auth_callback: Proc.new do @block_called ||= 0 @block_called += 1 auth.create_token_request(client_id: client_id) - end + end) end - it 'calls the block' do + it 'calls the Proc' do expect(@block_called).to eql(1) end - it 'uses the token request returned from the block when requesting a new token' do + it 'uses the token request returned from the callback when requesting a new token' do expect(token.client_id).to eql(client_id) end context 'for every subsequent #request_token' do - context 'without a provided block' do + context 'without a :auth_callback Proc' do it 'calls the originally provided block' do auth.request_token expect(@block_called).to eql(2) end end context 'with a provided block' do - it 'does not call the originally provided block and calls the new #request_token block' do - auth.request_token { @request_block_called = true; auth.create_token_request } + it 'does not call the originally provided Proc and calls the new #request_token :auth_callback Proc' do + auth.request_token(auth_callback: Proc.new { @request_block_called = true; auth.create_token_request }) expect(@block_called).to eql(1) expect(@request_block_called).to eql(true) end end end @@ -452,23 +539,23 @@ end describe '#create_token_request' do let(:ttl) { 60 * 60 } let(:capability) { { :foo => ["publish"] } } - let(:options) { Hash.new } - subject { auth.create_token_request(options) } + let(:token_request_options) { Hash.new } + subject { auth.create_token_request(token_request_options) } - it 'uses the key ID from the client' do - expect(subject['id']).to eql(key_id) + it 'uses the key name from the client' do + expect(subject['keyName']).to eql(key_name) end it 'uses the default TTL' do - expect(subject['ttl']).to eql(Ably::Models::Token::DEFAULTS[:ttl]) + expect(subject['ttl']).to eql(Ably::Auth::TOKEN_DEFAULTS.fetch(:ttl) * 1000) end it 'uses the default capability' do - expect(subject['capability']).to eql(Ably::Models::Token::DEFAULTS[:capability].to_json) + expect(subject['capability']).to eql(Ably::Auth::TOKEN_DEFAULTS.fetch(:capability).to_json) end context 'the nonce' do it 'is unique for every request' do unique_nonces = 100.times.map { auth.create_token_request['nonce'] } @@ -478,99 +565,104 @@ it 'is at least 16 characters' do expect(subject['nonce'].length).to be >= 16 end end - %w(ttl capability nonce timestamp client_id).each do |attribute| + %w(ttl nonce client_id).each do |attribute| context "with option :#{attribute}" do - let(:option_value) { random_int_str(1_000_000_000) } + let(:option_value) { random_int_str(1_000_000_000).to_i } before do - options[attribute.to_sym] = option_value + token_request_options[attribute.to_sym] = option_value end it "overrides default" do - expect(subject[convert_to_mixed_case(attribute)].to_s).to eql(option_value.to_s) + expect(subject.public_send(attribute).to_s).to eql(option_value.to_s) end end end context 'with additional invalid attributes' do - let(:options) { { nonce: 'valid', is_not_used_by_token_request: 'invalid' } } + let(:token_request_options) { { nonce: 'valid', is_not_used_by_token_request: 'invalid' } } specify 'are ignored' do - expect(subject.keys).to_not include(:is_not_used_by_token_request) - expect(subject.keys).to_not include(convert_to_mixed_case(:is_not_used_by_token_request)) - expect(subject.keys).to include('nonce') - expect(subject['nonce']).to eql('valid') + expect(subject.hash.keys).to_not include(:is_not_used_by_token_request) + expect(subject.hash.keys).to_not include(convert_to_mixed_case(:is_not_used_by_token_request)) + expect(subject.hash.keys).to include(:nonce) + expect(subject.nonce).to eql('valid') end end context 'when required fields are missing' do let(:client) { Ably::Rest::Client.new(auth_url: 'http://example.com', protocol: protocol) } it 'should raise an exception if key secret is missing' do - expect { auth.create_token_request(key_id: 'id') }.to raise_error Ably::Exceptions::TokenRequestError + expect { auth.create_token_request(key_name: 'name') }.to raise_error Ably::Exceptions::TokenRequestError end - it 'should raise an exception if key id is missing' do + it 'should raise an exception if key name is missing' do expect { auth.create_token_request(key_secret: 'secret') }.to raise_error Ably::Exceptions::TokenRequestError end end context 'with :query_time option' do let(:time) { Time.now - 30 } - let(:options) { { query_time: true } } + let(:token_request_options) { { query_time: true } } it 'queries the server for the timestamp' do expect(client).to receive(:time).and_return(time) - expect(subject['timestamp']).to eql(time.to_i) + expect(subject['timestamp']).to be_within(1).of(time.to_f * 1000) end end context 'with :timestamp option' do let(:token_request_time) { Time.now + 5 } - let(:options) { { timestamp: token_request_time } } + let(:token_request_options) { { timestamp: token_request_time } } it 'uses the provided timestamp in the token request' do - expect(subject['timestamp']).to eql(token_request_time.to_i) + expect(subject['timestamp']).to be_within(1).of(token_request_time.to_f * 1000) end end context 'signing' do - let(:options) do + let(:token_request_options) do { - id: random_str, - ttl: random_str, + key_name: random_str, + ttl: random_int_str.to_i, capability: random_str, client_id: random_str, - timestamp: random_int_str, + timestamp: random_int_str.to_i, nonce: random_str } end + # TokenRequest expects times in milliseconds, whereas create_token_request assumes Ruby default of seconds + let(:token_request_attributes) do + token_request_options.merge(timestamp: token_request_options[:timestamp] * 1000, ttl: token_request_options[:ttl] * 1000) + end + it 'generates a valid HMAC' do - hmac = hmac_for(options, key_secret) + hmac = hmac_for(Ably::Models::TokenRequest(token_request_attributes).hash, key_secret) expect(subject['mac']).to eql(hmac) end end end context 'using token authentication' do let(:capability) { { :foo => ["publish"] } } - describe 'with :token_id option' do + describe 'with :token option' do let(:ttl) { 60 * 60 } - let(:token) do + let(:token_details) do auth.request_token( ttl: ttl, capability: capability ) end - let(:token_id) { token.id } + let(:token) { token_details.token } let(:token_auth_client) do - Ably::Rest::Client.new(token_id: token_id, environment: environment, protocol: protocol) + Ably::Rest::Client.new(token: token, environment: environment, protocol: protocol) end - it 'authenticates successfully using the provided :token_id' do + it 'authenticates successfully using the provided :token' do expect(token_auth_client.channel('foo').publish('event', 'data')).to be_truthy end it 'disallows publishing on unspecified capability channels' do expect { token_auth_client.channel('bar').publish('event', 'data') }.to raise_error do |error| @@ -596,38 +688,36 @@ context 'when implicit as a result of using :client id' do let(:client_id) { '999' } let(:client) do Ably::Rest::Client.new(key: api_key, client_id: client_id, environment: environment, protocol: protocol) end - let(:token_id) { 'unique-token-id' } + let(:token) { 'unique-token' } let(:token_response) do { - access_token: { - id: token_id - } + token: token }.to_json end context 'and requests to the Ably server are mocked', :webmock do let!(:request_token_stub) do - stub_request(:post, "#{client.endpoint}/keys/#{key_id}/requestToken"). + stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken"). to_return(:status => 201, :body => token_response, :headers => { 'Content-Type' => 'application/json' }) end let!(:publish_message_stub) do stub_request(:post, "#{client.endpoint}/channels/foo/publish"). - with(headers: { 'Authorization' => "Bearer #{encode64(token_id)}" }). + with(headers: { 'Authorization' => "Bearer #{encode64(token)}" }). to_return(status: 201, body: '{}', headers: { 'Content-Type' => 'application/json' }) end it 'will send a token request to the server' do client.channel('foo').publish('event', 'data') expect(request_token_stub).to have_been_requested end end describe 'a token is created' do - let(:token) { client.auth.current_token } + let(:token) { client.auth.current_token_details } it 'before a request is made' do expect(token).to be_nil end @@ -636,15 +726,15 @@ end it 'with capability and TTL defaults' do client.channel('foo').publish('event', 'data') - expect(token).to be_a(Ably::Models::Token) - capability_with_str_key = Ably::Models::Token::DEFAULTS[:capability] - capability = Hash[capability_with_str_key.keys.map(&:to_sym).zip(capability_with_str_key.values)] - expect(token.capability).to eq(JSON.dump(capability)) - expect(token.expires_at.to_i).to be_within(2).of(Time.now.to_i + Ably::Models::Token::DEFAULTS[:ttl]) + expect(token).to be_a(Ably::Models::TokenDetails) + capability_with_str_key = Ably::Auth::TOKEN_DEFAULTS.fetch(:capability) + capability = Hash[capability_with_str_key.keys.map(&:to_s).zip(capability_with_str_key.values)] + expect(token.capability).to eq(capability) + expect(token.expires.to_i).to be_within(2).of(Time.now.to_i + Ably::Auth::TOKEN_DEFAULTS.fetch(:ttl)) expect(token.client_id).to eq(client_id) end end end end @@ -658,23 +748,9 @@ expect(auth.key).to eql(api_key) end specify '#using_basic_auth? is true' do expect(auth).to be_using_basic_auth - end - end - - context 'when using legacy :api_key option and basic auth' do - let(:client) do - Ably::Rest::Client.new(api_key: api_key, environment: environment, protocol: protocol) - end - - specify '#using_token_auth? is false' do - expect(auth).to_not be_using_token_auth - end - - specify '#key attribute contains the key string' do - expect(auth.key).to eql(api_key) end end end end