require 'authenticated_client' module SoarAuthenticationToken class RemoteTokenValidator def initialize(configuration) @configuration = configuration validate_configuration end def inject_store_provider(store_provider) #ignore the store provider since this validator does not use a store end def validate(authentication_token:,flow_identifier: nil) response = send_request(authentication_token,flow_identifier) validate_and_extract_information_from_response(response) end private def send_request(authentication_token,flow_identifier) uri = URI.parse(@configuration['validator-url']) uri.query = URI.encode_www_form( {'flow_identifier' => flow_identifier} ) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.is_a?(URI::HTTPS) request = Net::HTTP::Post.new(uri.request_uri) request.body = { 'authentication_token' => authentication_token }.to_json http.request(request) end def validate_and_extract_information_from_response(response) raise "Failure validating token with token validation service. Code #{response.code} received" if '200' != response.code body = JSON.parse(response.body) if ('success' == body['status']) and body['data'] token_validity = body['data']['token_validity'] token_meta = body['data']['token_meta'] message = body['data']['notifications'].first raise 'Token validation service did not provide token_validity' if token_validity.nil? raise 'Token validation service did not provide token_meta' if token_validity and token_meta.nil? raise 'Token validation service did not provide message' if message.nil? return [token_validity, token_meta, message] end if 'fail' == body['status'] return rejection_result(reason: 'remote validation failed') end raise "Failure validating token with token validation service. Status '#{body['status']}' received" end def validate_configuration raise "'validator-url' must be configured in remote mode" unless @configuration['validator-url'] end def rejection_result(reason:) [false, nil, reason] end end end