diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb index 78160ea9..d36e1ed8 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb @@ -1,6 +1,7 @@ require 'inferno/dsl/oauth_credentials' require_relative 'endpoints/resource_api_endpoint' require_relative 'endpoints/token_endpoint' +require_relative 'endpoints/authorize_endpoint' require_relative 'endpoints/next_page_endpoint' require_relative 'endpoints/resource_id_endpoint' @@ -77,7 +78,9 @@ def self.test_resumes?(test) end end - suite_endpoint :post, TOKEN_PATH, TokenEndpoint + suite_endpoint :post, TOKEN_PATH, MockAuthorization::TokenEndpoint + suite_endpoint :get, AUTH_PATH, MockAuthorization::AuthorizeEndpoint + suite_endpoint :post, AUTH_PATH, MockAuthorization::AuthorizeEndpoint suite_endpoint :get, PATIENT_PATH, ResourceAPIEndpoint @@ -100,6 +103,7 @@ def self.test_resumes?(test) end route(:get, METADATA_PATH, get_metadata) + route(:get, SMART_CONFIG_PATH, carin_smart_config) group do run_as_group diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb index dc49dd34..f7376dd2 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientCoverageSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is a Coverage resource that conforms to the CARIN for Blue Button [Coverage profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Coverage.html). ) - input :access_token run do resources = previous_resource_requests(:Coverage) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb index e9eb7618..9104edbc 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientEOBInpatientSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource that conforms to the CARIN for Blue Button [Outpatient Institutional ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Outpatient-Institutional.html). ) - input :access_token run do resources = previous_resource_requests(:ExplanationOfBenefit_Inpatient_Institutional) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb index cb77037a..44d45c42 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientEOBOralSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource that conforms to the CARIN for Blue Button [Oral ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Oral.html). ) - input :access_token run do resources = previous_resource_requests(:ExplanationOfBenefit_Oral) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb index 32b01919..2e9cd899 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientEOBOutpatientSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource that conforms to the CARIN for Blue Button [Outpatient Institutional ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Outpatient-Institutional.html). ) - input :access_token run do resources = previous_resource_requests(:ExplanationOfBenefit_Outpatient_Institutional) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb index 284b0521..396d0d52 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientEOBPharmacySubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource that conforms to the CARIN for Blue Button [Pharmacy ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Pharmacy.html). ) - input :access_token run do resources = previous_resource_requests(:ExplanationOfBenefit_Pharmacy) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb index a3387df4..8a5eede4 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientEOBProfessionalSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource that conforms to the CARIN for Blue Button [Professional NonClinician ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Professional-NonClinician.html). ) - input :access_token run do resources = previous_resource_requests(:ExplanationOfBenefit_Professional_NonClinician) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb index c66908d0..9cab9ff7 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientOrganizationSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is an Organization resource that conforms to the CARIN for Blue Button [Organization profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Organization.html). ) - input :access_token run do resources = previous_resource_requests(:Organization) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb index f6be7c84..a4c4e808 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientPatientSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is a Patient resource that conforms to the CARIN for Blue Button [Patient profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Patient.html). ) - input :access_token run do resources = previous_resource_requests(:Patient) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb index d3682d02..9e742e61 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientPractitionerSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is a Practitioner resource that conforms to the CARIN for Blue Button [Practitioner profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Practitioner.html). ) - input :access_token run do resources = previous_resource_requests(:Practitioner) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb index e765dd82..be1ae5cf 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb @@ -12,7 +12,6 @@ class C4BBClientRelatedPersonSubmitClaimsDataRequestTest < Inferno::Test This test verifies that an instance returned by requests made by the client is a RelatedPerson resource that conforms to the CARIN for Blue Button [RelatedPerson profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-RelatedPerson.html). ) - input :access_token run do resources = previous_resource_requests(:RelatedPerson) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/authorize_endpoint.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/authorize_endpoint.rb new file mode 100644 index 00000000..b9830190 --- /dev/null +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/authorize_endpoint.rb @@ -0,0 +1,32 @@ +module CarinForBlueButtonTestKit + module MockAuthorization + class AuthorizeEndpoint < Inferno::DSL::SuiteEndpoint + def test_run_identifier + request.params[:client_id] + end + + def tags + [AUTHORIZE_TAG] + end + + def make_response + if request.params[:redirect_uri].present? + redirect_uri = "#{request.params[:redirect_uri]}?" \ + "code=#{SecureRandom.hex}&" \ + "state=#{request.params[:state]}" + response.status = 302 + response.headers['Location'] = redirect_uri + else + response.status = 400 + response.format = 'application/fhir+json' + response.body = FHIR::OperationOutcome.new( + issue: FHIR::OperationOutcome::Issue.new(severity: 'fatal', code: 'required', + details: FHIR::CodeableConcept.new( + text: 'No redirect_uri provided' + )) + ).to_json + end + end + end + end +end diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb index df2bd2bf..7fe092bd 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb @@ -1,24 +1,125 @@ require_relative '../tags' +require_relative '../urls' require_relative '../mock_server' module CarinForBlueButtonTestKit - class TokenEndpoint < Inferno::DSL::SuiteEndpoint - include CarinForBlueButtonTestKit::MockServer + module MockAuthorization + AUTHORIZED_PRACTITIONER_ID = 'c4bb-Practitioner'.freeze # Must exist on the FHIR_REFERENCE_SERVER (env var) - def test_run_identifier - extract_client_id(request) - end + class TokenEndpoint < Inferno::DSL::SuiteEndpoint + include CarinForBlueButtonTestKit::MockServer - def make_response - token_response(request) - end + def test_run_identifier + extract_client_id + end - def tags - [AUTH_TAG] - end + def tags + [TOKEN_TAG] + end + + def make_response + client_id = extract_client_id + access_token = client_id + granted_scopes = SUPPORTED_SCOPES & requested_scopes + + response_hash = { access_token:, scope: granted_scopes.join(' '), token_type: 'bearer', + expires_in: 3600 } + + if granted_scopes.include?('openid') + response_hash.merge!(id_token: create_id_token(client_id, + fhir_user: granted_scopes.include?('fhirUser'))) + end + + # fhir_context_input = find_test_input("#{input_group_prefix}_smart_fhir_context") + # begin + # fhir_context = JSON.parse(fhir_context_input) + # rescue StandardError + # fhir_context = nil + # end + # response_hash.merge!(fhirContext: fhir_context) if fhir_context + + # smart_patient_input = find_test_input("#{input_group_prefix}_smart_patient_id") + # response_hash.merge!(patient: smart_patient_input) if smart_patient_input + + response_hash.merge!(patient: '888') + + response.body = response_hash.to_json + response.headers['Cache-Control'] = 'no-store' + response.headers['Pragma'] = 'no-cache' + response.headers['Access-Control-Allow-Origin'] = '*' + response.status = 200 + end + + private + + def extract_client_id + # Public client || confidential client asymmetric || confidential client symmetric + request.params[:client_id] || extract_client_id_from_client_assertion || extract_client_id_from_basic_auth + end + + def extract_client_id_from_client_assertion + encoded_jwt = request.params[:client_assertion] + return unless encoded_jwt.present? + + jwt_payload = + begin + JWT.decode(encoded_jwt, nil, false)&.first # skip signature verification + rescue StandardError + nil + end + + jwt_payload['iss'] || jwt_payload['sub'] if jwt_payload.present? + end + + def input_group_prefix + if test.id.include?('static') + 'static' + elsif test.id.include?('adaptive') + 'adaptive' + else + 'resp' + end + end + + def find_test_input(input_name) + JSON.parse(result.input_json)&.find { |input| input['name'] == input_name }&.dig('value') + end + + def extract_client_id_from_basic_auth + encoded_credentials = request.headers['authorization']&.delete_prefix('Basic ') + return unless encoded_credentials.present? + + decoded_credentials = Base64.decode64(encoded_credentials) + decoded_credentials&.split(':')&.first + end + + def requested_scopes + auth_request = requests_repo.tagged_requests(result.test_session_id, [AUTHORIZE_TAG]).last + return [] unless auth_request + + auth_params = if auth_request.verb.downcase == 'get' + auth_request.query_parameters + else + URI.decode_www_form(auth_request.request_body)&.to_h + end + scope_str = auth_params&.dig('scope') + scope_str ? URI.decode_www_form_component(scope_str).split : [] + end + + def create_id_token(client_id, fhir_user: false) + # No point in mocking an identity provider, just always use known Practitioner as the authorized user + suite_fhir_base_url = request.url.split(TOKEN_PATH).first + BASE_FHIR_PATH + id_token_hash = { + iss: suite_fhir_base_url, + sub: AUTHORIZED_PRACTITIONER_ID, + aud: client_id, + exp: Time.now.to_i + (24 * 60 * 60), # 24 hrs + iat: Time.now.to_i + } + id_token_hash.merge!(fhirUser: "#{suite_fhir_base_url}/Practitioner/#{AUTHORIZED_PRACTITIONER_ID}") if fhir_user - def update_result - results_repo.update(result.id, result: 'pass') unless test.config.options[:accepts_multiple_requests] + JWT.encode(id_token_hash, RSA_PRIVATE_KEY, 'RS256') + end end end end diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb index 0e02b0f8..68ede6de 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb @@ -8,14 +8,20 @@ class C4BBClientInitialWaitTest < Inferno::Test description %( This test will receive claims data requests and search requests until the user confirms they are done. ) - input :access_token + input :client_id, + title: 'Client ID', + description: %( + Enter the client ID you will use to connect to this CARIN server via SMART. This client ID will be sent + back as the access token to send requests to this server. + ) + config options: { accepts_multiple_requests: true } run do wait( - identifier: access_token, + identifier: client_id, message: %( - Access Token: #{access_token} \n + Access Token: #{client_id} \n Submit CARIN requests via the following method: * Single Resource API: `#{submit_url}?:search_params`, with `:endpoint` replaced with the endpoint you want to reach and `:search_params` replaced with the search parameters for the request. @@ -67,7 +73,7 @@ class C4BBClientInitialWaitTest < Inferno::Test * ExplanationOfBenefit:payee * ExplanationOfBenefit:* - [Click here](#{resume_claims_data_url}?token=#{access_token}) when done. + [Click here](#{resume_claims_data_url}?token=#{client_id}) when done. ), timeout: 900 ) diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json b/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json.erb similarity index 95% rename from lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json rename to lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json.erb index f9c8ac80..7fe48c0e 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json.erb @@ -23,6 +23,34 @@ { "mode": "server", "documentation": "The C4BB Server **SHALL**:\n\n1. Support all profiles defined in this Implementation Guide..\n2. Implement the RESTful behavior according to the FHIR specification.\n3. Return the following response classes:\n - (Status 400): invalid parameter\n - (Status 401/4xx): unauthorized request\n - (Status 403): insufficient scope\n - (Status 404): unknown resource\n - (Status 410): deleted resource.\n4. Support json source formats for all CARIN-BB interactions.\n5. Identify the CARIN-BB profiles supported as part of the FHIR `meta.profile` attribute for each instance.\n6. Support the searchParameters on each profile individually and in combination.\n\nThe C4BB Server **SHOULD**:\n\n1. Support xml source formats for all C4BB interactions.\n", + "security": { + "extension": [ + { + "url": "http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris", + "extension": [ + { + "url": "token", + "valueUri": "<%= Inferno::Application['base_url'] %>/custom/c4bb_v200_client/mock_auth/token" + }, + { + "url": "authorize", + "valueUri": "<%= Inferno::Application['base_url'] %>/custom/c4bb_v200_client/mock_auth/authorization" + } + ] + } + ], + "service": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/restful-security-service", + "code": "SMART-on-FHIR" + } + ], + "text": "OAuth2 using SMART-on-FHIR profile (see http://docs.smarthealthit.org)" + } + ] + }, "resource": [ { "extension": [ diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb index 4d5122c0..edd1c060 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb @@ -2,7 +2,6 @@ require_relative 'urls' require_relative 'collection' require_relative 'client_validation_test' -# require_relative 'metadata/mock_capability_statement' module CarinForBlueButtonTestKit # Serve responses to CARIN requests @@ -13,6 +12,10 @@ module CarinForBlueButtonTestKit module MockServer include URLs + SUPPORTED_SCOPES = ['launch', 'patient/*.rs', 'user/*.rs', 'offline_access', 'openid', 'fhirUser'].freeze + RSA_PRIVATE_KEY = OpenSSL::PKey::RSA.generate(2048) + RSA_PUBLIC_KEY = RSA_PRIVATE_KEY.public_key + def server_proxy @server_proxy ||= Faraday.new( url: ENV.fetch('FHIR_REFERENCE_SERVER'), @@ -25,12 +28,6 @@ def server_proxy end end - def token_response(request, _test = nil, _test_result = nil) - # Placeholder for a more complete mock token endpoint - response.body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 300 }.to_json - response.status = 200 - end - def error_response_resource(request) server_response = server_proxy.get('Patient', { _id: 888 }) response_resource = FHIR.from_contents(server_response.body) @@ -97,9 +94,42 @@ def read_next_page(request, test = nil, test_result = nil) end def get_metadata + erb_template = ERB.new( + File.read( + 'lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json.erb' + ) + ) + capability_statement = JSON.parse(erb_template.result).to_json + proc { [200, { 'Content-Type' => 'application/fhir+json;charset=utf-8' }, - [File.read('lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json')]] + [capability_statement]] + } + end + + def carin_smart_config + response_body = + { + authorization_endpoint: authorization_url, + token_endpoint: token_url, + token_endpoint_auth_methods_supported: ['private_key_jwt'], + token_endpoint_auth_signing_alg_values_supported: ['RS256'], + grant_types_supported: ['authorization_code'], + scopes_supported: SUPPORTED_SCOPES, + response_types_supported: ['code'], + code_challenge_methods_supported: ['S256'], + capabilities: [ + 'launch-ehr', + 'permission-patient', + 'permission-user', + 'client-public', + 'client-confidential-symmetric', + 'client-confidential-asymmetric' + ] + }.to_json + + proc { + [200, { 'Content-Type' => 'application/json', 'Access-Control-Allow-Origin' => '*' }, [response_body]] } end diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb index d972d9a3..cadb63f6 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb @@ -17,7 +17,6 @@ class C4BBClientCoverageRequiredSearches < Inferno::Test * _id * patient ) - input :access_token verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14' diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb index 0c2304f6..20da4cf0 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb @@ -31,7 +31,6 @@ class C4BBClientEOBRequiredSearches < Inferno::Test * ExplanationOfBenefit:payee * ExplanationOfBenefit:* ) - input :access_token verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14' diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb index d4a5b6de..60700558 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb @@ -18,7 +18,6 @@ class C4BBClientOrganizationRequiredSearches < Inferno::Test * name * address ) - input :access_token verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14' diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb index dfdf3ed0..9efef777 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb @@ -26,7 +26,6 @@ class C4BBClientPatientRequiredSearches < Inferno::Test * birthdate+name * gender+name ) - input :access_token verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14' diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb index a62a6d19..1463d610 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb @@ -18,7 +18,6 @@ class C4BBClientPractitionerRequiredSearches < Inferno::Test * name * identifier ) - input :access_token verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14' diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb index a8f9db9e..bf966671 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb @@ -16,7 +16,6 @@ class C4BBClientRelatedPersonRequiredSearches < Inferno::Test Capability Statements: * _id ) - input :access_token verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14' diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb index 9f553c15..747b1cfb 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb @@ -4,4 +4,6 @@ module CarinForBlueButtonTestKit AUTH_TAG = 'carin_auth' RESOURCE_API_TAG = 'carin_resource_api' RESOURCE_ID_TAG = 'carin_resource_id' + AUTHORIZE_TAG = 'carin_smart_app_authorize' + TOKEN_TAG = 'carin_smart_app_token' end diff --git a/lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb b/lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb index b322bce8..fa4d010f 100644 --- a/lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb +++ b/lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb @@ -1,5 +1,7 @@ module CarinForBlueButtonTestKit TOKEN_PATH = '/mock_auth/token' + AUTH_PATH = '/mock_auth/authorization' + SMART_CONFIG_PATH = '/.well-known/smart-configuration' PATIENT_PATH = '/fhir/Patient' RESOURCE_API_PATH = '/fhir/:endpoint' RESOURCE_ID_PATH = '/fhir/:endpoint/:id' @@ -18,6 +20,14 @@ def token_url @token_url ||= base_url + TOKEN_PATH end + def authorization_url + @authorization_url ||= base_url + AUTH_PATH + end + + def smart_configuration_url + @smart_configuration_url ||= base_url + SMART_CONFIG_PATH + end + def base_fhir_url @base_fhir_url ||= base_url + BASE_FHIR_PATH end diff --git a/spec/carin_for_blue_button/c4bb_client/c4bb_client_eob_required_searches_spec.rb b/spec/carin_for_blue_button/c4bb_client/c4bb_client_eob_required_searches_spec.rb index 8c3758ba..ca3f3f2b 100644 --- a/spec/carin_for_blue_button/c4bb_client/c4bb_client_eob_required_searches_spec.rb +++ b/spec/carin_for_blue_button/c4bb_client/c4bb_client_eob_required_searches_spec.rb @@ -183,14 +183,14 @@ def run(runnable, inputs = {}) make_all_eob_search_requests(eob_required_searches) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('pass') end it 'skips if no EOB search requests were made' do allow(test).to receive(:suite).and_return(suite) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('skip') expect(result.result_message).to eq('No search requests made for Explanation of Benefit resource') end @@ -201,7 +201,7 @@ def run(runnable, inputs = {}) eob_required_searches.pop make_all_eob_search_requests(eob_required_searches) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('fail') expect(result.result_message).to match(/_id/) end diff --git a/spec/carin_for_blue_button/c4bb_client/c4bb_client_initial_wait_test_spec.rb b/spec/carin_for_blue_button/c4bb_client/c4bb_client_initial_wait_test_spec.rb index 4c5fc959..47f3bb16 100644 --- a/spec/carin_for_blue_button/c4bb_client/c4bb_client_initial_wait_test_spec.rb +++ b/spec/carin_for_blue_button/c4bb_client/c4bb_client_initial_wait_test_spec.rb @@ -26,10 +26,10 @@ let(:server_patient_api_request) { "#{fhir_server}#{patient_endpoint}" } let(:server_eob_include_search) { "#{fhir_server}#{eob_include_search_endpoint}" } - let(:access_token) { 'SAMPLE_TOKEN' } + let(:client_id) { 'SAMPLE_TOKEN' } let(:resume_pass_url) do - "#{Inferno::Application['base_url']}/custom/c4bb_v200_client/resume_claims_data?token=#{access_token}" + "#{Inferno::Application['base_url']}/custom/c4bb_v200_client/resume_claims_data?token=#{client_id}" end let(:c4bb_eob_include_bundle) do @@ -78,16 +78,16 @@ def run(runnable, inputs = {}) allow(test).to receive_messages(suite:, parent: suite) patient_fhir_api_request = stub_request(:get, server_patient_api_request) - .with( - headers: { 'Authorization' => "Bearer #{access_token}" } - ) - .to_return(status: 200, body: c4bb_patient_search_bundle.to_json) + .with( + headers: { 'Authorization' => "Bearer #{client_id}" } + ) + .to_return(status: 200, body: c4bb_patient_search_bundle.to_json) - result = run(test, access_token:) + result = run(test, client_id:) expect(result.result).to eq('wait') - header 'Authorization', "Bearer #{access_token}" + header 'Authorization', "Bearer #{client_id}" get(patient_api_request) expect(last_response).to be_ok @@ -106,16 +106,16 @@ def run(runnable, inputs = {}) allow(test).to receive_messages(suite:, parent: suite) eob_fhir_include_search = stub_request(:get, server_eob_include_search) - .with( - headers: { 'Authorization' => "Bearer #{access_token}" } - ) - .to_return(status: 200, body: c4bb_eob_include_bundle.to_json) + .with( + headers: { 'Authorization' => "Bearer #{client_id}" } + ) + .to_return(status: 200, body: c4bb_eob_include_bundle.to_json) - result = run(test, access_token:) + result = run(test, client_id:) expect(result.result).to eq('wait') - header 'Authorization', "Bearer #{access_token}" + header 'Authorization', "Bearer #{client_id}" get(eob_include_search) expect(last_response).to be_ok @@ -150,7 +150,7 @@ def run(runnable, inputs = {}) it 'Responds 500 if Bearer token is incorrect' do allow(test).to receive_messages(suite:, parent: suite) - result = run(test, access_token:) + result = run(test, client_id:) header 'Authorization', 'Bearer WRONG_TOKEN' get(patient_api_request) @@ -170,14 +170,14 @@ def run(runnable, inputs = {}) allow(test).to receive_messages(suite:, parent: suite) patient_fhir_api_request = stub_request(:get, server_patient_api_request) - .with( - headers: { 'Authorization' => "Bearer #{access_token}" } - ) - .to_return(status: 200, body: c4bb_patient_search_bundle.to_json) + .with( + headers: { 'Authorization' => "Bearer #{client_id}" } + ) + .to_return(status: 200, body: c4bb_patient_search_bundle.to_json) - result = run(test, access_token:) + result = run(test, client_id:) - header 'Authorization', "Bearer #{access_token}" + header 'Authorization', "Bearer #{client_id}" get(invalid_patient_api_request) expect(last_response.status).to eq(403) @@ -199,16 +199,16 @@ def run(runnable, inputs = {}) allow(test).to receive_messages(suite:, parent: suite) patient_fhir_api_request = stub_request(:get, server_patient_api_request) - .with( - headers: { 'Authorization' => "Bearer #{access_token}" } - ) - .to_return(status: 404, body: c4bb_patient_search_bundle.to_json) + .with( + headers: { 'Authorization' => "Bearer #{client_id}" } + ) + .to_return(status: 404, body: c4bb_patient_search_bundle.to_json) - result = run(test, access_token:) + result = run(test, client_id:) expect(result.result).to eq('wait') - header 'Authorization', "Bearer #{access_token}" + header 'Authorization', "Bearer #{client_id}" get(patient_api_request) expect(last_response.status).to eq(404) diff --git a/spec/carin_for_blue_button/c4bb_client/c4bb_client_patient_submit_claims_data_request_test_spec.rb b/spec/carin_for_blue_button/c4bb_client/c4bb_client_patient_submit_claims_data_request_test_spec.rb index c35d36db..f48a450b 100644 --- a/spec/carin_for_blue_button/c4bb_client/c4bb_client_patient_submit_claims_data_request_test_spec.rb +++ b/spec/carin_for_blue_button/c4bb_client/c4bb_client_patient_submit_claims_data_request_test_spec.rb @@ -105,7 +105,7 @@ def run(runnable, inputs = {}) create_fhir_api_request(body: JSON.parse(c4bb_patient_search_bundle.to_json)) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('pass') end @@ -115,7 +115,7 @@ def run(runnable, inputs = {}) create_fhir_api_request(url: eob_include_search, body: JSON.parse(c4bb_eob_include_bundle.to_json), tags: eob_include_search_tags) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('pass') end @@ -125,7 +125,7 @@ def run(runnable, inputs = {}) c4bb_patient_search_bundle.entry.first.resource.id = 999 create_fhir_api_request(body: JSON.parse(c4bb_patient_search_bundle.to_json)) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('fail') expect(result.result_message).to eq('Unable to find expected resource: 888') end @@ -139,7 +139,7 @@ def run(runnable, inputs = {}) create_fhir_api_request(url: eob_include_search, body: JSON.parse(c4bb_eob_include_bundle.to_json), tags: eob_include_search_tags - ['Patient']) - result = run(test, access_token:) + result = run(test) expect(result.result).to eq('skip') expect(result.result_message).to eq('No requests made for Patient resources') end