lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb in ably-rest-0.8.5 vs lib/submodules/ably-ruby/spec/acceptance/rest/auth_spec.rb in ably-rest-0.8.6
- old
+ new
@@ -195,10 +195,89 @@
expect(client).to_not receive(:time)
auth.request_token({}, options)
end
end
+ context 'with :auth_url option merging', :webmock do
+ context 'with existing configured auth options' do
+ let(:client_id) { random_str }
+ let(:auth_url) { "https://www.fictitious.com/#{random_str}" }
+ let(:auth_method) { :get }
+ let(:auth_params) { { key: 'val', client_id: 'isOverridenByClient' } }
+ let(:auth_headers) { { 'Header-X' => 'val1', 'Header-Y' => 'val2' } }
+
+ let(:base_options) do
+ default_options.merge(
+ client_id: client_id,
+ auth_url: auth_url,
+ auth_params: auth_params,
+ auth_headers: auth_headers
+ )
+ end
+ let(:client_options) { base_options }
+
+ let!(:auth_request) do
+ stub_request(auth_method, auth_url).to_return(
+ :status => 201,
+ :body => '123123.12312321321312321', # token string
+ :headers => { 'Content-Type' => 'text/plain' }
+ )
+ end
+
+ let(:request_token_auth_options) { Hash.new }
+ let(:request_token_token_params) { Hash.new }
+ after do
+ client.auth.request_token(request_token_token_params, request_token_auth_options)
+ expect(auth_request).to have_been_requested
+ end
+
+ context 'using unspecified :auth_method' do
+ it 'requests a token using a GET request with provided headers, and merges client_id into auth_params' do
+ auth_request.with(headers: auth_headers)
+ auth_request.with(query: auth_params.merge(client_id: client_id))
+ end
+
+ context 'with provided token_params' do
+ let(:request_token_token_params) { { client_id: 'custom', key2: 'val2' } }
+
+ it 'merges provided token_params with existing auth_params and client_id' do
+ auth_request.with(query: auth_params.merge(client_id: client_id).merge(request_token_token_params))
+ end
+ end
+
+ context 'with provided auth option auth_params and auth_headers' do
+ let(:request_token_auth_options) { { auth_params: {}, auth_headers: {} } }
+
+ it 'replaces any preconfigured auth_params' do
+ auth_request.with(query: {}.merge(client_id: client_id))
+ auth_request.with(headers: { 'Accept'=>'*/*' }) # mock library needs at least one header, accept is default
+ end
+ end
+ end
+
+ context 'using :get :auth_method and query params in the URL' do
+ let(:auth_method) { :get }
+ let(:client_options) { base_options.merge(auth_method: :get, auth_url: "#{auth_url}?urlparam=true") }
+
+ it 'requests a token using a GET request with provided headers, and merges client_id into auth_params and existing URL querystring into new URL querystring' do
+ auth_request.with(headers: auth_headers)
+ auth_request.with(query: auth_params.merge(client_id: client_id).merge(urlparam: 'true'))
+ end
+ end
+
+ context 'using :post :auth_method' do
+ let(:auth_method) { :post }
+ let(:client_options) { base_options.merge(auth_method: :post) }
+
+ it 'requests a token using a POST request with provided headers, and merges client_id into auth_params as form-encoded post data' do
+ auth_request.with(headers: auth_headers)
+ auth_request.with(body: auth_params.merge(client_id: client_id))
+ end
+ end
+ end
+ end
+
context 'with :auth_url option', :webmock do
let(:auth_url) { 'https://www.fictitious.com/get_token' }
let(:auth_url_response) { { keyName: key_name }.to_json }
let(:token_response) { {} }
let(:query_params) { nil }
@@ -363,10 +442,22 @@
end
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
+
+ context 'when authorised' do
+ before { auth.authorise(token_params, auth_callback: auth_callback) }
+
+ it "sets Auth#client_id to the new token's client_id" do
+ expect(auth.client_id).to eql(client_id)
+ end
+
+ it "sets Client#client_id to the new token's client_id" do
+ expect(client.client_id).to eql(client_id)
+ end
+ end
end
context 'that returns a TokenDetails JSON object' do
let(:client_id) { random_str }
let(:token_params){ { client_id: client_id } }
@@ -375,22 +466,26 @@
let(:expires) { Time.now + 60}
let(:capability) { {'foo'=>['publish']} }
let(:capability_str) { JSON.dump(capability) }
let!(:token_details) do
- auth.request_token(token_params, auth_callback: Proc.new do |token_params_arg|
+ auth.request_token(token_params, auth_callback: auth_callback)
+ end
+
+ let(:auth_callback) do
+ 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)
+ 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(token_params)
@@ -402,10 +497,22 @@
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
+
+ context 'when authorised' do
+ before { auth.authorise(token_params, auth_callback: auth_callback) }
+
+ it "sets Auth#client_id to the new token's client_id" do
+ expect(auth.client_id).to eql(client_id)
+ end
+
+ it "sets Client#client_id to the new token's client_id" do
+ expect(client.client_id).to eql(client_id)
+ end
+ end
end
context 'that returns a TokenDetails object' do
let(:client_id) { random_str }
@@ -600,10 +707,41 @@
expect { client.stats }.to change { client.auth.current_token_details }
expect(@block_called).to eql(1)
end
end
end
+
+ context 'with an explicit ClientOptions client_id' do
+ let(:client_id) { random_str }
+ let(:client_options) { default_options.merge(auth_callback: Proc.new { auth_token_object }, client_id: client_id) }
+ let(:auth_client) { Ably::Rest::Client.new(default_options.merge(key: api_key, client_id: 'invalid')) }
+
+ context 'and an incompatible client_id in a TokenDetails object passed to the auth callback' do
+ let(:auth_token_object) { auth_client.auth.request_token }
+
+ it 'rejects a TokenDetails object with an incompatible client_id and raises an exception' do
+ expect { client.auth.authorise({}, force: true) }.to raise_error Ably::Exceptions::IncompatibleClientId
+ end
+ end
+
+ context 'and an incompatible client_id in a TokenRequest object passed to the auth callback and raises an exception' do
+ let(:auth_token_object) { auth_client.auth.create_token_request }
+
+ it 'rejects a TokenRequests object with an incompatible client_id and raises an exception' do
+ expect { client.auth.authorise({}, force: true) }.to raise_error Ably::Exceptions::IncompatibleClientId
+ end
+ end
+
+ context 'and a token string without any retrievable client_id' do
+ let(:auth_token_object) { auth_client.auth.request_token(client_id: 'different').token }
+
+ it 'rejects a TokenRequests object with an incompatible client_id and raises an exception' do
+ client.auth.authorise({}, force: true)
+ expect(client.client_id).to eql(client_id)
+ end
+ end
+ end
end
describe '#create_token_request' do
let(:ttl) { 60 * 60 }
let(:capability) { { "foo" => ["publish"] } }
@@ -797,11 +935,11 @@
it 'cannot be renewed automatically' do
expect(token_auth_client.auth).to_not be_token_renewable
end
end
- context 'when implicit as a result of using :client id' do
+ 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) { 'unique-token' }
@@ -847,14 +985,94 @@
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
+
+ specify '#client_id contains the client_id' do
+ expect(client.auth.client_id).to eql(client_id)
+ end
end
end
+
+ context 'when :client_id is provided in a token' do
+ let(:client_id) { '123' }
+ let(:token) do
+ Ably::Rest::Client.new(key: api_key, environment: environment, protocol: protocol).auth.request_token(client_id: client_id)
+ end
+ let(:client) do
+ Ably::Rest::Client.new(token: token, environment: environment, protocol: protocol)
+ end
+
+ specify '#client_id contains the client_id' do
+ expect(client.auth.client_id).to eql(client_id)
+ end
+ end
end
- context 'when using an :key and basic auth' do
+ describe '#client_id_validated?' do
+ let(:auth) { Ably::Rest::Client.new(default_options.merge(key: api_key)).auth }
+
+ context 'when using basic auth' do
+ let(:client_options) { default_options.merge(key: api_key) }
+
+ it 'is false as basic auth users do not have an identity' do
+ expect(client.auth).to_not be_client_id_validated
+ end
+ end
+
+ context 'when using a token auth string for a token with a client_id' do
+ let(:client_options) { default_options.merge(token: auth.request_token(client_id: 'present').token) }
+
+ it 'is false as identification is not possible from an opaque token string' do
+ expect(client.auth).to_not be_client_id_validated
+ end
+ end
+
+ context 'when using a token' do
+ context 'with a client_id' do
+ let(:client_options) { default_options.merge(token: auth.request_token(client_id: 'present')) }
+
+ it 'is true' do
+ expect(client.auth).to be_client_id_validated
+ end
+ end
+
+ context 'with no client_id (anonymous)' do
+ let(:client_options) { default_options.merge(token: auth.request_token(client_id: nil)) }
+
+ it 'is true' do
+ expect(client.auth).to be_client_id_validated
+ end
+ end
+
+ context 'with a wildcard client_id (anonymous)' do
+ let(:client_options) { default_options.merge(token: auth.request_token(client_id: '*')) }
+
+ it 'is false' do
+ expect(client.auth).to be_client_id_validated
+ end
+ end
+ end
+
+ context 'when using a token request with a client_id' do
+ let(:client_options) { default_options.merge(token: auth.create_token_request(client_id: 'present')) }
+
+ it 'is not true as identification is not confirmed until authenticated' do
+ expect(client.auth).to_not be_client_id_validated
+ end
+
+ context 'after authentication' do
+ before { client.channel('test').publish('a') }
+
+ it 'is true as identification is completed during implicit authentication' do
+ expect(client.auth).to be_client_id_validated
+ end
+ end
+ end
+ end
+
+ context 'when using a :key and basic auth' do
specify '#using_token_auth? is false' do
expect(auth).to_not be_using_token_auth
end
specify '#key attribute contains the key string' do