require 'httparty' require 'net/http' class MockHttpResponse def initialize(**opts) opts.each do |key, val| instance_variable_set("@#{key}", val) end end def code; @code; end def headers; @headers; end def parsed_response; @body; end end describe Capcoauth::OAuth::TokenVerifier do subject { Capcoauth::OAuth::TokenVerifier } describe '#verify' do before do Capcoauth.configuration.client_id = 'verifier_test_client_id' end it 'raises UnauthorizedError when no access token object passed' do expect{subject.verify(nil)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Please log in to continue') end it 'raises UnauthorizedError when access token object has no token material' do expect{subject.verify(Capcoauth::OAuth::AccessToken.new(nil))}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Please log in to continue') end it 'returns access token object if access_token is valid' do Capcoauth::OAuth::TTLCache.update('abc', '123') token = Capcoauth::OAuth::AccessToken.new('abc') expect(subject.verify(token)).to equal(token) Capcoauth::OAuth::TTLCache.remove('abc') end it 'calls HTTParty.get and raises OtherError on Net::OpenTimeout' do httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_raise(Net::OpenTimeout) token = Capcoauth::OAuth::AccessToken.new('iamnew') expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::OtherError, 'An error occurred while verifying your credentials (server not available)') end it 'calls HTTParty.get and raises UnauthorizedError if ID type is not returned' do Capcoauth.configuration.user_id_field = :psoft httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: { 'resource_owner_id' => '123', 'external_ids' => {} })) token = Capcoauth::OAuth::AccessToken.new('iamnew') expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'The system cannot recognize you by that ID type') Capcoauth.configuration.user_id_field = :capcoauth end it 'calls HTTParty.get and raises UnauthorizedError if ID type is not returned' do httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: { 'resource_owner_id' => '123', 'application' => { 'uid' => 'not_client_id_123' } })) token = Capcoauth::OAuth::AccessToken.new('iamnew') expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Your credentials are valid, but are not for use with this system') end it 'calls HTTParty.get and raises UnauthorizedError if token is unknown' do httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 401, body: { 'error': 'invalid_request', 'error_description': 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.' })) token = Capcoauth::OAuth::AccessToken.new('iamnew') expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::UnauthorizedError, 'Please log in to continue') end it 'calls HTTParty.get and raises UnauthorizedError if token is unknown' do httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 12345, body: { 'error': 'invalid_request', 'error_description': 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.' })) token = Capcoauth::OAuth::AccessToken.new('iamnew') expect{subject.verify(token)}.to raise_error(Capcoauth::OAuth::TokenVerifier::OtherError, 'An error occurred while verifying your credentials (unknown response)') end it 'calls HTTParty.get and returns access token with capcoauth id type' do httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: { 'resource_owner_id' => 'capcoauth_123', 'application' => { 'uid' => 'verifier_test_client_id' } })) token = Capcoauth::OAuth::AccessToken.new('capcoauth_user_token') expect(subject.verify(token)).to equal(token) expect(token.user_id).to eq('capcoauth_123') Capcoauth::OAuth::TTLCache.remove('capcoauth_user_token') end it 'calls HTTParty.get and returns access token with psoft id type' do Capcoauth.configuration.user_id_field = :psoft httparty_double = class_double('HTTParty').as_stubbed_const expect(httparty_double).to receive(:get).and_return(MockHttpResponse.new(code: 200, body: { 'resource_owner_id' => '123', 'application' => { 'uid' => 'verifier_test_client_id' }, 'external_ids' => { 'psoft' => 'psoft_123' } })) token = Capcoauth::OAuth::AccessToken.new('psoft_user_token') expect(subject.verify(token)).to equal(token) expect(token.user_id).to eq('psoft_123') Capcoauth::OAuth::TTLCache.remove('psoft_user_token') Capcoauth.configuration.user_id_field = :capcoauth end end end