require 'spec_helper' require 'yaml' require 'webmock/rspec' describe SoarAuthenticationToken::RemoteTokenValidator do subject { SoarAuthenticationToken::RemoteTokenValidator } before :all do @test_store = AuthTokenStoreProvider::StubClient.new keypair_generator = SoarAuthenticationToken::KeypairGenerator.new @valid_private_key, @valid_public_key = keypair_generator.generate @invalid_private_key, @invalid_public_key = keypair_generator.generate @test_identifier = 'a@b.co.za' @local_invalid_generator_configuration = { 'provider' => 'SoarAuthenticationToken::JwtTokenGenerator', 'private_key' => @invalid_private_key } @remote_generator_configuration = { 'provider' => 'SoarAuthenticationToken::RemoteTokenGenerator', 'generator-url' => 'http://authentication-token-generator-service:9393/generate', 'generator-client-auth-token' => 'test_ecosystem_token_for_auth_token_aaapi_authenticator_service' } @remote_validator_configuration = { 'provider' => 'SoarAuthenticationToken::RemoteTokenValidator', 'validator-url' => 'http://authentication-token-validator-service:9393/validate', 'generator-client-auth-token' => 'test_ecosystem_token_for_auth_token_aaapi_authenticator_service' } @local_invalid_generator = SoarAuthenticationToken::TokenGenerator.new(@local_invalid_generator_configuration) @local_invalid_generator.inject_store_provider(@test_store) @remote_generator = SoarAuthenticationToken::TokenGenerator.new(@remote_generator_configuration) end it 'has a version number' do expect(SoarAuthenticationToken::VERSION).not_to be nil end describe "#validate" do let!(:iut) { subject.new(@remote_validator_configuration) } context 'given valid token' do it 'should indicate valid if the token is valid' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => @test_identifier }, 'notifications' => ['none'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}", headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: stub_response_body, headers: {}) token = 'valid_token' token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil) expect(token_validity).to eq true end it 'should provide the authenticated_identifier if the token is valid' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => true, 'token_meta' => { 'authenticated_identifier' => @test_identifier }, 'notifications' => ['none'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). with(body: "{\"authentication_token\":\"valid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}", headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: stub_response_body, headers: {}) token = 'valid_token' token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil) expect(token_meta['authenticated_identifier']).to eq @test_identifier end end context 'given invalid (generalized) token' do it 'indicate token is invalid' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). with(body: "{\"authentication_token\":\"invalid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}", headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: stub_response_body, headers: {}) token = 'invalid_token' token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil) expect(token_validity).to eq false end it 'does not provide the token meta' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). with(body: "{\"authentication_token\":\"invalid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}", headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: stub_response_body, headers: {}) token = 'invalid_token' token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil) expect(token_meta).to eq nil end it 'provides a message indicating the token is invalid' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). with(body: "{\"authentication_token\":\"invalid_token\",\"request_information\":{\"source_address\":\"1.1.1.1\",\"user_agent\":\"some shiny browser\",\"service\":\"test-service\",\"resource\":\"/\"}}", headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: stub_response_body, headers: {}) token = 'invalid_token' token_validity, token_meta, message = iut.validate(authentication_token: token, request_information: request_information_from_valid_source, flow_identifier: nil) expect(message).to match /Token decode\/verification failure/ end end context 'given invalid token validator url that will result in timeouts' do it 'raise error after attempt that timeout has occured' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). to_timeout.times(2) expect{ iut.validate(authentication_token: 'some_token', request_information: {}, flow_identifier: nil) }.to raise_error Timeout::Error end it 'by default attempts 2 times with 3 second timeout' do stub_response_body = {'status' => 'success', 'data' => { 'token_validity' => false, 'token_meta' => nil, 'notifications' => ['Token decode/verification failure'] }}.to_json stub_request(:post, "http://authentication-token-validator-service:9393/validate?flow_identifier"). to_timeout.times(2) expect{ iut.validate(authentication_token: 'some_token', request_information: {}, flow_identifier: nil) }.to raise_error Timeout::Error end end end end