lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb in ably-rest-0.8.3 vs lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb in ably-rest-0.8.5
- old
+ new
@@ -25,11 +25,11 @@
)
end
vary_by_protocol do
let(:default_options) { { environment: environment, protocol: protocol } }
- let(:client_options) { default_options.merge(key: api_key) }
+ let(:client_options) { default_options.merge(key: api_key) }
let(:client) do
Ably::Rest::Client.new(client_options)
end
let(:auth) { client.auth }
let(:content_type) do
@@ -64,14 +64,14 @@
describe '#request_token' do
let(:ttl) { 30 * 60 }
let(:capability) { { :foo => ['publish'] } }
let(:token_details) do
- auth.request_token(token_params: {
+ auth.request_token(
ttl: ttl,
capability: capability
- })
+ )
end
it 'creates a TokenRequest automatically and sends it to Ably to obtain a token', webmock: true do
token_request_stub = stub_request(:post, "#{client.endpoint}/keys/#{key_name}/requestToken").
to_return(status: 201, body: serialize({}, protocol), headers: { 'Content-Type' => content_type })
@@ -110,11 +110,11 @@
:body => serialize(token_response, protocol),
:headers => { 'Content-Type' => content_type }
)
end
- before { auth.request_token token_params: token_params }
+ before { auth.request_token token_params }
it "overrides default and uses camelCase notation for attributes" do
expect(request_token_stub).to have_been_requested
end
end
@@ -124,11 +124,11 @@
let(:key_name) { "app.#{random_str}" }
let(:key_secret) { random_str }
let(:nonce) { random_str }
let(:auth_options) { { key: "#{key_name}:#{key_secret}" } }
let(:token_params) { { nonce: nonce, timestamp: Time.now } }
- let(:token_request) { auth.create_token_request(auth_options, token_params) }
+ let(:token_request) { auth.create_token_request(token_params, auth_options) }
let(:mac) do
hmac_for(token_request, key_secret)
end
let(:token_response) { {} }
@@ -140,11 +140,11 @@
:status => 201,
:body => serialize(token_response, protocol),
:headers => { 'Content-Type' => content_type })
end
- let!(:token) { auth.request_token(auth_options, token_params) }
+ let!(:token) { auth.request_token(token_params, auth_options) }
specify 'key_name is used in request and signing uses key_secret' do
expect(request_token_stub).to have_been_requested
end
end
@@ -154,11 +154,11 @@
let(:key_secret) { random_str }
let(:nonce) { random_str }
let(:auth_options) { { key_name: key_name, key_secret: key_secret } }
let(:token_params) { { nonce: nonce, timestamp: Time.now } }
- let(:token_request) { auth.create_token_request(auth_options, token_params) }
+ let(:token_request) { auth.create_token_request(token_params, auth_options) }
let(:mac) do
hmac_for(token_request, key_secret)
end
let(:token_response) { {} }
@@ -170,11 +170,11 @@
:status => 201,
:body => serialize(token_response, protocol),
:headers => { 'Content-Type' => content_type })
end
- let!(:token) { auth.request_token(auth_options, token_params) }
+ let!(:token) { auth.request_token(token_params, auth_options) }
specify 'key_name is used in request and signing uses key_secret' do
expect(request_token_stub).to have_been_requested
end
end
@@ -182,20 +182,20 @@
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
- auth.request_token(options)
+ auth.request_token({}, options)
end
end
context 'without :query_time option' do
let(:options) { { query_time: false } }
it 'does not query the server for the time' do
expect(client).to_not receive(:time)
- auth.request_token(options)
+ auth.request_token({}, options)
end
end
context 'with :auth_url option', :webmock do
let(:auth_url) { 'https://www.fictitious.com/get_token' }
@@ -235,11 +235,11 @@
:headers => { 'Content-Type' => content_type }
)
end
context 'when response from :auth_url is a valid token request' do
- let!(:token) { auth.request_token(auth_options) }
+ let!(:token) { auth.request_token({}, auth_options) }
it 'requests a token from :auth_url using an HTTP GET request' do
expect(request_token_stub).to have_been_requested
expect(auth_url_request_stub).to have_been_requested
end
@@ -288,11 +288,11 @@
'expires' => expires.to_i * 1000,
'capability'=> capability_str
}.to_json
end
- let!(:token_details) { auth.request_token(auth_options) }
+ let!(:token_details) { auth.request_token({}, auth_options) }
it 'returns TokenDetails created from the token JSON' do
expect(auth_url_request_stub).to have_been_requested
expect(request_token_stub).to_not have_been_requested
expect(token_details).to be_a(Ably::Models::TokenDetails)
@@ -306,11 +306,11 @@
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(auth_options) }
+ let!(:token_details) { auth.request_token({}, auth_options) }
it 'returns TokenDetails created from the token JSON' do
expect(auth_url_request_stub).to have_been_requested
expect(request_token_stub).to_not have_been_requested
expect(token_details).to be_a(Ably::Models::TokenDetails)
@@ -323,22 +323,22 @@
let!(:auth_url_request_stub) do
stub_request(auth_method, auth_url).to_return(:status => 500)
end
it 'raises ServerError' do
- expect { auth.request_token auth_options }.to raise_error(Ably::Exceptions::ServerError)
+ expect { auth.request_token({}, auth_options) }.to raise_error(Ably::Exceptions::ServerError)
end
end
context 'XML' do
let!(:auth_url_request_stub) do
stub_request(auth_method, auth_url).
to_return(:status => 201, :body => '<xml></xml>', :headers => { 'Content-Type' => 'application/xml' })
end
it 'raises InvalidResponseBody' do
- expect { auth.request_token auth_options }.to raise_error(Ably::Exceptions::InvalidResponseBody)
+ expect { auth.request_token({}, auth_options) }.to raise_error(Ably::Exceptions::InvalidResponseBody)
end
end
end
end
@@ -348,16 +348,16 @@
let(:ttl) { 8888 }
let(:auth_callback) do
Proc.new do |token_params_arg|
@block_called = true
expect(token_params_arg).to eq(token_params)
- auth.create_token_request(token_params: { client_id: client_id })
+ auth.create_token_request(client_id: client_id)
end
end
let(:token_params) { { ttl: ttl } }
let!(:request_token) do
- auth.request_token(auth_callback: auth_callback, token_params: token_params)
+ auth.request_token(token_params, auth_callback: auth_callback)
end
it 'calls the Proc with token_params when authenticating to obtain the request token' do
expect(@block_called).to eql(true)
end
@@ -367,35 +367,35 @@
end
end
context 'that returns a TokenDetails JSON object' do
let(:client_id) { random_str }
- let(:options) { { client_id: client_id } }
+ let(:token_params){ { 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!(:token_details) do
- auth.request_token(auth_callback: Proc.new do |token_params_arg|
+ auth.request_token(token_params, auth_callback: Proc.new do |token_params_arg|
@block_called = true
@block_params = token_params_arg
{
'token' => token,
'keyName' => 'J_0Tlg.NxCRig',
'clientId' => client_id,
'issued' => issued.to_i * 1000,
'expires' => expires.to_i * 1000,
'capability'=> capability_str
}
- end, token_params: options)
+ end)
end
it 'calls the Proc when authenticating to obtain the request token' do
expect(@block_called).to eql(true)
- expect(@block_params).to include(options)
+ expect(@block_params).to include(token_params)
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)
@@ -408,14 +408,12 @@
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(token_params: {
- client_id: client_id
- })
+ 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)
@@ -426,11 +424,11 @@
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|
+ 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
@@ -438,14 +436,13 @@
expect(token_details.token).to eql(token)
end
end
end
- context 'persisted option', api_private: true do
+ context 'persisted option of token params', api_private: true do
context 'when set to true', api_private: true do
- let(:options) { { persisted: true } }
- let(:token_details) { auth.request_token(token_params: options) }
+ let(:token_details) { auth.request_token(persisted: true) }
it 'returns a token with a short token ID that is used to look up the token details' do
expect(token_details.token.length).to be < 64
expect(token_details.token).to match(/^#{app_id}\.A/)
end
@@ -460,20 +457,20 @@
end
end
context 'with auth_option :client_id' do
let(:client_id) { random_str }
- let(:token_details) { 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_details.client_id).to eql(client_id)
end
end
context 'with token_param :client_id' do
let(:client_id) { random_str }
- let(:token_details) { auth.request_token(token_params: { 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_details.client_id).to eql(client_id)
end
end
@@ -493,12 +490,12 @@
let(:token_params) do
{ ttl: 55 }
end
it 'passes all auth_options and token_params to #request_token' do
- expect(auth).to receive(:request_token).with(auth_options, token_params)
- auth.authorise auth_options, token_params
+ expect(auth).to receive(:request_token).with(token_params, auth_options)
+ auth.authorise token_params, auth_options
end
it 'returns a valid token' do
expect(auth.authorise).to be_a(Ably::Models::TokenDetails)
end
@@ -524,24 +521,30 @@
expect(auth).to receive(:request_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_details }
+ expect { auth.authorise({}, force: true) }.to change { auth.current_token_details }
end
end
- it 'updates the persisted auth options that are then used for subsequent authorise requests' do
- expect(auth.options[:ttl]).to_not eql(26)
+ it 'updates the persisted token params that are then used for subsequent authorise requests' do
+ expect(auth.token_params[:ttl]).to_not eql(26)
auth.authorise(ttl: 26)
- expect(auth.options[:ttl]).to eql(26)
+ expect(auth.token_params[:ttl]).to eql(26)
end
+ it 'updates the persisted token params that are then used for subsequent authorise requests' do
+ expect(auth.options[:query_time]).to_not eql(true)
+ auth.authorise({}, query_time: true)
+ expect(auth.options[:query_time]).to eql(true)
+ end
+
context 'with a Proc for the :auth_callback option' do
let(:client_id) { random_str }
let!(:token) do
- auth.authorise(auth_callback: Proc.new do
+ auth.authorise({}, auth_callback: Proc.new do
@block_called ||= 0
@block_called += 1
auth.create_token_request(client_id: client_id)
end)
end
@@ -562,25 +565,53 @@
end
end
context 'with a provided block' do
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 })
+ 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
end
+
+ context 'with an explicit token string that expires' do
+ context 'and a Proc for the :auth_callback option to provide a means to renew the token' do
+ before do
+ # Ensure a soon to expire token is not treated as expired
+ stub_const 'Ably::Models::TokenDetails::TOKEN_EXPIRY_BUFFER', 0
+ old_token_defaults = Ably::Auth::TOKEN_DEFAULTS
+ stub_const 'Ably::Auth::TOKEN_DEFAULTS', old_token_defaults.merge(renew_token_buffer: 0)
+ end
+
+ let(:token_client) { Ably::Rest::Client.new(default_options.merge(key: api_key, token_params: { ttl: 3 })) }
+ let(:client_options) {
+ default_options.merge(token: token_client.auth.request_token.token, auth_callback: Proc.new do
+ @block_called ||= 0
+ @block_called += 1
+ token_client.auth.create_token_request
+ end)
+ }
+
+ it 'calls the Proc once the token has expired and the new token is used' do
+ client.stats
+ expect(@block_called).to be_nil
+ sleep 3.5
+ expect { client.stats }.to change { client.auth.current_token_details }
+ expect(@block_called).to eql(1)
+ end
+ end
+ end
end
describe '#create_token_request' do
let(:ttl) { 60 * 60 }
let(:capability) { { "foo" => ["publish"] } }
let(:token_params) { Hash.new }
- subject { auth.create_token_request(token_params: token_params) }
+ subject { auth.create_token_request(token_params) }
it 'returns a TokenRequest object' do
expect(subject).to be_a(Ably::Models::TokenRequest)
end
@@ -664,24 +695,24 @@
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_name: 'name') }.to raise_error Ably::Exceptions::TokenRequestFailed
+ expect { auth.create_token_request({}, key_name: 'name') }.to raise_error Ably::Exceptions::TokenRequestFailed
end
it 'should raise an exception if key name is missing' do
- expect { auth.create_token_request(key_secret: 'secret') }.to raise_error Ably::Exceptions::TokenRequestFailed
+ expect { auth.create_token_request({}, key_secret: 'secret') }.to raise_error Ably::Exceptions::TokenRequestFailed
end
end
context 'timestamp attribute' do
context 'with :query_time auth_option' do
let(:time) { Time.now - 30 }
let(:auth_options) { { query_time: true } }
- subject { auth.create_token_request(auth_options) }
+ subject { auth.create_token_request({}, auth_options) }
it 'queries the server for the timestamp' do
expect(client).to receive(:time).and_return(time)
expect(subject['timestamp']).to be_within(1).of(time.to_f * 1000)
end
@@ -731,14 +762,14 @@
let(:capability) { { :foo => ["publish"] } }
describe 'with :token option' do
let(:ttl) { 60 * 60 }
let(:token_details) do
- auth.request_token(token_params: {
+ auth.request_token(
ttl: ttl,
capability: capability
- })
+ )
end
let(:token) { token_details.token }
let(:token_auth_client) do
Ably::Rest::Client.new(token: token, environment: environment, protocol: protocol)
end
@@ -754,10 +785,10 @@
expect(error.code).to eql(40160)
end
end
it 'fails if timestamp is invalid' do
- expect { auth.request_token(token_params: { timestamp: Time.now - 180 }) }.to raise_error do |error|
+ expect { auth.request_token(timestamp: Time.now - 180) }.to raise_error do |error|
expect(error).to be_a(Ably::Exceptions::InvalidRequest)
expect(error.status).to eql(401)
expect(error.code).to eql(40101)
end
end