carin_for_blue_button_test_kit 0.13.3 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/carin_cpcds_client_ri.json +12 -0
  3. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/c4bb_client_test_suite.rb +17 -4
  4. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/coverage_claims_data_request_test.rb +0 -1
  5. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_inpatient_claims_data_request_test.rb +0 -1
  6. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_oral_claims_data_request_test.rb +0 -1
  7. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_outpatient_claims_data_request_test.rb +0 -1
  8. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_pharmacy_claims_data_request_test.rb +0 -1
  9. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/eob_professional_claims_data_request_test.rb +0 -1
  10. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/organization_claims_data_request_test.rb +0 -1
  11. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/patient_claims_data_request_test.rb +0 -1
  12. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/practitioner_claims_data_request_test.rb +0 -1
  13. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/claim_data_request_tests/relatedperson_claims_data_request_test.rb +0 -1
  14. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/authorize_endpoint.rb +32 -0
  15. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/next_page_endpoint.rb +3 -1
  16. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/resource_api_endpoint.rb +3 -1
  17. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/resource_id_endpoint.rb +3 -1
  18. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/endpoints/token_endpoint.rb +69 -13
  19. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/initial_wait_test.rb +35 -4
  20. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/{mock_capability_statement.json → mock_capability_statement.json.erb} +28 -0
  21. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_authorization.rb +35 -0
  22. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/mock_server.rb +43 -9
  23. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/coverage_required_searches.rb +0 -1
  24. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/eob_required_searches.rb +0 -1
  25. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/organization_required_searches.rb +0 -1
  26. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/patient_required_searches.rb +0 -1
  27. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/practitioner_required_searches.rb +0 -1
  28. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/required_searches_tests/relatedperson_required_searches.rb +0 -1
  29. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/tags.rb +2 -0
  30. data/lib/carin_for_blue_button_test_kit/client/v2.0.0/urls.rb +25 -10
  31. data/lib/carin_for_blue_button_test_kit/docs/carin_for_blue_button_v2.0.0_client_suite_description.md +7 -4
  32. data/lib/carin_for_blue_button_test_kit/generated/v1.1.0/c4bb_test_suite.rb +9 -1
  33. data/lib/carin_for_blue_button_test_kit/generated/v2.0.0/c4bb_test_suite.rb +9 -1
  34. data/lib/carin_for_blue_button_test_kit/generated/v2.0.0-dev-nonfinancial/c4bb_test_suite.rb +9 -1
  35. data/lib/carin_for_blue_button_test_kit/generator/templates/group.rb.erb +24 -0
  36. data/lib/carin_for_blue_button_test_kit/generator/templates/include_search.rb.erb +37 -0
  37. data/lib/carin_for_blue_button_test_kit/generator/templates/must_support.rb.erb +44 -0
  38. data/lib/carin_for_blue_button_test_kit/generator/templates/read.rb.erb +38 -0
  39. data/lib/carin_for_blue_button_test_kit/generator/templates/resource_list.rb.erb +9 -0
  40. data/lib/carin_for_blue_button_test_kit/generator/templates/search.rb.erb +43 -0
  41. data/lib/carin_for_blue_button_test_kit/generator/templates/suite.rb.erb +92 -0
  42. data/lib/carin_for_blue_button_test_kit/generator/templates/validation.rb.erb +34 -0
  43. data/lib/carin_for_blue_button_test_kit/metadata.rb +70 -0
  44. data/lib/carin_for_blue_button_test_kit/requirements/carin-for-blue-button-test-kit_out_of_scope_requirements.csv +53 -0
  45. data/lib/carin_for_blue_button_test_kit/requirements/carin-for-blue-button-test-kit_requirements.csv +335 -0
  46. data/lib/carin_for_blue_button_test_kit/requirements/generated/carin-for-blue-button-test-kit_requirements_coverage.csv +335 -0
  47. data/lib/carin_for_blue_button_test_kit/version.rb +2 -1
  48. data/lib/carin_for_blue_button_test_kit.rb +1 -0
  49. data/lib/inferno_requirements_tools/rake/rakefile_template +31 -0
  50. data/lib/requirements_config.yaml +14 -0
  51. metadata +27 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ddcfc1b502d40c9e506ac6219457d4f810ac18ce1cc520e448c4b96f609ed2d
4
- data.tar.gz: 9cb13ece58d5934e9b62482594c5c2d1ef55c49ec3cad5f034db45f64c9b5156
3
+ metadata.gz: ea990f355ce17cde4cd012adc06141cb44bf6c3c70a8bc73de0faa9d3f3c2102
4
+ data.tar.gz: 58e4f6efca2020589024a8cbb11959ed159f58ff00690a3d85f57fd9fea6f7c3
5
5
  SHA512:
6
- metadata.gz: a171f8af69738d3c1d85fb0ad4186ef50257f3e6fe43c01f3d4fc118bfab940e6638d480842a4160e1881334eb11435e67e6fa12524acfc2ac45fd7b7ca7f478
7
- data.tar.gz: 1cb33dfb109fac99d85d2096f08d99a03dba45f43e2e62386ab62a4c5d5601222d29089e175becf7eb9ab6fddab9cfa94dfd05d69f45e4036a57cade90661099
6
+ metadata.gz: 22e6ea91cf9494db944a339344b23c80386bbe6ccfb2ef085264467a334c98eca1905acf8ab9d9b5c604b89379816ef8f867bfaf65b62f7ba5ffd838eada51f1
7
+ data.tar.gz: 23fd00d94577114d623bbeef68b15ff2e121de486b24082a66eace0cb915eee51b1d34215582cfa1aad39236aff17fab4af21959532199b266ff7d65351415fb
@@ -0,0 +1,12 @@
1
+ {
2
+ "title": "CARIN CPCDS Reference Implementation Client",
3
+ "id": "carin_cpcds_client_ri_preset",
4
+ "test_suite_id": "c4bb_v200_client",
5
+ "inputs": [
6
+ {
7
+ "name": "client_id",
8
+ "type": "text",
9
+ "value": "SAMPLE_CLIENT_ID"
10
+ }
11
+ ]
12
+ }
@@ -1,6 +1,7 @@
1
1
  require 'inferno/dsl/oauth_credentials'
2
2
  require_relative 'endpoints/resource_api_endpoint'
3
3
  require_relative 'endpoints/token_endpoint'
4
+ require_relative 'endpoints/authorize_endpoint'
4
5
  require_relative 'endpoints/next_page_endpoint'
5
6
  require_relative 'endpoints/resource_id_endpoint'
6
7
 
@@ -77,7 +78,9 @@ module CarinForBlueButtonTestKit
77
78
  end
78
79
  end
79
80
 
80
- suite_endpoint :post, TOKEN_PATH, TokenEndpoint
81
+ suite_endpoint :post, TOKEN_PATH, MockAuthorization::TokenEndpoint
82
+ suite_endpoint :get, AUTH_PATH, MockAuthorization::AuthorizeEndpoint
83
+ suite_endpoint :post, AUTH_PATH, MockAuthorization::AuthorizeEndpoint
81
84
 
82
85
  suite_endpoint :get, PATIENT_PATH, ResourceAPIEndpoint
83
86
 
@@ -87,11 +90,11 @@ module CarinForBlueButtonTestKit
87
90
 
88
91
  suite_endpoint :get, BASE_FHIR_PATH, NextPageEndpoint
89
92
 
90
- resume_test_route :get, RESUME_PASS_PATH do |request|
91
- C4BBV200ClientSuite.extract_token_from_query_params(request)
93
+ resume_test_route :get, RESUME_CLAIMS_DATA_PATH do |request|
94
+ C4BBV200ClientSuite.extract_test_run_identifier_from_query_params(request)
92
95
  end
93
96
 
94
- resume_test_route :get, RESUME_CLAIMS_DATA_PATH do |request|
97
+ resume_test_route :get, RESUME_PASS_PATH do |request|
95
98
  C4BBV200ClientSuite.extract_token_from_query_params(request)
96
99
  end
97
100
 
@@ -100,6 +103,8 @@ module CarinForBlueButtonTestKit
100
103
  end
101
104
 
102
105
  route(:get, METADATA_PATH, get_metadata)
106
+ route(:get, SMART_CONFIG_PATH, carin_smart_config)
107
+ route(:get, JKWS_PATH, MockAuthorization.method(:jwks))
103
108
 
104
109
  group do
105
110
  run_as_group
@@ -111,6 +116,7 @@ module CarinForBlueButtonTestKit
111
116
  [C4BB CapabilityStatement](https://hl7.org/fhir/us/carin-bb/STU2/CapabilityStatement-c4bb.html) and the
112
117
  [US Core Client CapabilityStatement](https://hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html).
113
118
  )
119
+ id :c4bb_claims_data_wait_test_group
114
120
 
115
121
  test from: :c4bb_v200_initial_wait_test
116
122
  end
@@ -125,6 +131,7 @@ module CarinForBlueButtonTestKit
125
131
  and the [US Core Client](https://www.hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html#patient)
126
132
  Capability Statements.
127
133
  )
134
+ id :c4bb_patient_profile_test_group
128
135
 
129
136
  test from: :patient_claims_data_request_test
130
137
  test from: :patient_required_searches
@@ -140,6 +147,7 @@ module CarinForBlueButtonTestKit
140
147
  and the [US Core Client](https://www.hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html)
141
148
  Capability Statements.
142
149
  )
150
+ id :c4bb_coverage_profile_test_group
143
151
 
144
152
  test from: :coverage_claims_data_request_test
145
153
  test from: :coverage_required_searches
@@ -155,6 +163,7 @@ module CarinForBlueButtonTestKit
155
163
  and the [US Core Client](https://www.hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html#organization)
156
164
  Capability Statements.
157
165
  )
166
+ id :c4bb_organization_profile_test_group
158
167
  optional
159
168
 
160
169
  test from: :organization_claims_data_request_test
@@ -171,6 +180,7 @@ module CarinForBlueButtonTestKit
171
180
  and the [US Core Client](https://www.hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html#practitioner)
172
181
  Capability Statements.
173
182
  )
183
+ id :c4bb_practitioner_profile_test_group
174
184
  optional
175
185
 
176
186
  test from: :practitioner_claims_data_request_test
@@ -187,6 +197,7 @@ module CarinForBlueButtonTestKit
187
197
  and the [US Core Client](https://www.hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html)
188
198
  Capability Statements.
189
199
  )
200
+ id :c4bb_relatedperson_profile_test_group
190
201
  optional
191
202
 
192
203
  test from: :relatedperson_claims_data_request_test
@@ -204,6 +215,7 @@ module CarinForBlueButtonTestKit
204
215
  and the [US Core Client](https://www.hl7.org/fhir/us/core/STU3.1.1/CapabilityStatement-us-core-client.html)
205
216
  Capability Statements.
206
217
  )
218
+ id :c4bb_explanationofbenefit_profiles_test_group
207
219
 
208
220
  test from: :eob_inpatient_claims_data_request_test
209
221
  test from: :eob_outpatient_claims_data_request_test
@@ -220,6 +232,7 @@ module CarinForBlueButtonTestKit
220
232
  Attest that the client system under test was able to sucessfully process all of the requested resources for
221
233
  each of the CARIN for Blue Button profiles.
222
234
  )
235
+ id :c4bb_client_attestation_test_group
223
236
 
224
237
  test from: :client_claims_data_attestation
225
238
  end
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is a Coverage resource
13
13
  that conforms to the CARIN for Blue Button [Coverage profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Coverage.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:Coverage)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource
13
13
  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).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:ExplanationOfBenefit_Inpatient_Institutional)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource
13
13
  that conforms to the CARIN for Blue Button [Oral ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Oral.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:ExplanationOfBenefit_Oral)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource
13
13
  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).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:ExplanationOfBenefit_Outpatient_Institutional)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource
13
13
  that conforms to the CARIN for Blue Button [Pharmacy ExplanationOfBenefit profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-ExplanationOfBenefit-Pharmacy.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:ExplanationOfBenefit_Pharmacy)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is an ExplanationOfBenefit resource
13
13
  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).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:ExplanationOfBenefit_Professional_NonClinician)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is an Organization resource
13
13
  that conforms to the CARIN for Blue Button [Organization profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Organization.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:Organization)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is a Patient resource
13
13
  that conforms to the CARIN for Blue Button [Patient profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Patient.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:Patient)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is a Practitioner resource
13
13
  that conforms to the CARIN for Blue Button [Practitioner profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-Practitioner.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:Practitioner)
@@ -12,7 +12,6 @@ module CarinForBlueButtonTestKit
12
12
  This test verifies that an instance returned by requests made by the client is a RelatedPerson resource
13
13
  that conforms to the CARIN for Blue Button [RelatedPerson profile](https://hl7.org/fhir/us/carin-bb/STU2/StructureDefinition-C4BB-RelatedPerson.html).
14
14
  )
15
- input :access_token
16
15
 
17
16
  run do
18
17
  resources = previous_resource_requests(:RelatedPerson)
@@ -0,0 +1,32 @@
1
+ module CarinForBlueButtonTestKit
2
+ module MockAuthorization
3
+ class AuthorizeEndpoint < Inferno::DSL::SuiteEndpoint
4
+ def test_run_identifier
5
+ request.params[:client_id]
6
+ end
7
+
8
+ def tags
9
+ [AUTHORIZE_TAG]
10
+ end
11
+
12
+ def make_response
13
+ if request.params[:redirect_uri].present?
14
+ redirect_uri = "#{request.params[:redirect_uri]}?" \
15
+ "code=#{SecureRandom.hex}&" \
16
+ "state=#{request.params[:state]}"
17
+ response.status = 302
18
+ response.headers['Location'] = redirect_uri
19
+ else
20
+ response.status = 400
21
+ response.format = 'application/fhir+json'
22
+ response.body = FHIR::OperationOutcome.new(
23
+ issue: FHIR::OperationOutcome::Issue.new(severity: 'fatal', code: 'required',
24
+ details: FHIR::CodeableConcept.new(
25
+ text: 'No redirect_uri provided'
26
+ ))
27
+ ).to_json
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,12 +1,14 @@
1
1
  require_relative '../tags'
2
2
  require_relative '../mock_server'
3
+ require_relative '../mock_authorization'
3
4
 
4
5
  module CarinForBlueButtonTestKit
5
6
  class NextPageEndpoint < Inferno::DSL::SuiteEndpoint
6
7
  include CarinForBlueButtonTestKit::MockServer
8
+ include CarinForBlueButtonTestKit::MockAuthorization
7
9
 
8
10
  def test_run_identifier
9
- extract_bearer_token(request)
11
+ extract_client_id_from_bearer_token(request)
10
12
  end
11
13
 
12
14
  def make_response
@@ -1,14 +1,16 @@
1
1
  require_relative '../tags'
2
2
  require_relative '../mock_server'
3
+ require_relative '../mock_authorization'
3
4
  require_relative '../client_validation_test'
4
5
 
5
6
  module CarinForBlueButtonTestKit
6
7
  class ResourceAPIEndpoint < Inferno::DSL::SuiteEndpoint
7
8
  include CarinForBlueButtonTestKit::MockServer
9
+ include CarinForBlueButtonTestKit::MockAuthorization
8
10
  include CarinForBlueButtonTestKit::ClientValidationTest
9
11
 
10
12
  def test_run_identifier
11
- extract_bearer_token(request)
13
+ extract_client_id_from_bearer_token(request)
12
14
  end
13
15
 
14
16
  def make_response
@@ -1,12 +1,14 @@
1
1
  require_relative '../tags'
2
2
  require_relative '../mock_server'
3
+ require_relative '../mock_authorization'
3
4
 
4
5
  module CarinForBlueButtonTestKit
5
6
  class ResourceIDEndpoint < Inferno::DSL::SuiteEndpoint
6
7
  include CarinForBlueButtonTestKit::MockServer
8
+ include CarinForBlueButtonTestKit::MockAuthorization
7
9
 
8
10
  def test_run_identifier
9
- extract_bearer_token(request)
11
+ extract_client_id_from_bearer_token(request)
10
12
  end
11
13
 
12
14
  def make_response
@@ -1,24 +1,80 @@
1
1
  require_relative '../tags'
2
+ require_relative '../urls'
2
3
  require_relative '../mock_server'
4
+ require_relative '../mock_authorization'
3
5
 
4
6
  module CarinForBlueButtonTestKit
5
- class TokenEndpoint < Inferno::DSL::SuiteEndpoint
6
- include CarinForBlueButtonTestKit::MockServer
7
+ module MockAuthorization
8
+ CARIN_PATIENT_ID = '888'.freeze # Must exist on the FHIR_REFERENCE_SERVER (env var)
7
9
 
8
- def test_run_identifier
9
- extract_client_id(request)
10
- end
10
+ class TokenEndpoint < Inferno::DSL::SuiteEndpoint
11
+ include CarinForBlueButtonTestKit::MockServer
11
12
 
12
- def make_response
13
- token_response(request)
14
- end
13
+ def test_run_identifier
14
+ extract_client_id
15
+ end
15
16
 
16
- def tags
17
- [AUTH_TAG]
18
- end
17
+ def tags
18
+ [TOKEN_TAG]
19
+ end
20
+
21
+ def make_response
22
+ client_id = extract_client_id
23
+ access_token = JWT.encode({ inferno_client_id: client_id }, nil, 'none')
24
+ granted_scopes = SUPPORTED_SCOPES & requested_scopes
25
+
26
+ response_hash = { access_token:, scope: granted_scopes.join(' '), token_type: 'bearer',
27
+ expires_in: 3600 }
28
+
29
+ response_hash.merge!(patient: CARIN_PATIENT_ID)
30
+
31
+ response.body = response_hash.to_json
32
+ response.headers['Cache-Control'] = 'no-store'
33
+ response.headers['Pragma'] = 'no-cache'
34
+ response.status = 200
35
+ end
36
+
37
+ private
38
+
39
+ def extract_client_id
40
+ # Public client || confidential client asymmetric || confidential client symmetric
41
+ request.params[:client_id] || extract_client_id_from_client_assertion || extract_client_id_from_basic_auth
42
+ end
43
+
44
+ def extract_client_id_from_client_assertion
45
+ encoded_jwt = request.params[:client_assertion]
46
+ return unless encoded_jwt.present?
47
+
48
+ jwt_payload =
49
+ begin
50
+ JWT.decode(encoded_jwt, nil, false)&.first # skip signature verification
51
+ rescue StandardError
52
+ nil
53
+ end
54
+
55
+ jwt_payload['iss'] || jwt_payload['sub'] if jwt_payload.present?
56
+ end
57
+
58
+ def extract_client_id_from_basic_auth
59
+ encoded_credentials = request.headers['authorization']&.delete_prefix('Basic ')
60
+ return unless encoded_credentials.present?
61
+
62
+ decoded_credentials = Base64.decode64(encoded_credentials)
63
+ decoded_credentials&.split(':')&.first
64
+ end
65
+
66
+ def requested_scopes
67
+ auth_request = requests_repo.tagged_requests(result.test_session_id, [AUTHORIZE_TAG]).last
68
+ return [] unless auth_request
19
69
 
20
- def update_result
21
- results_repo.update(result.id, result: 'pass') unless test.config.options[:accepts_multiple_requests]
70
+ auth_params = if auth_request.verb.downcase == 'get'
71
+ auth_request.query_parameters
72
+ else
73
+ URI.decode_www_form(auth_request.request_body)&.to_h
74
+ end
75
+ scope_str = auth_params&.dig('scope')
76
+ scope_str ? URI.decode_www_form_component(scope_str).split : []
77
+ end
22
78
  end
23
79
  end
24
80
  end
@@ -8,14 +8,44 @@ module CarinForBlueButtonTestKit
8
8
  description %(
9
9
  This test will receive claims data requests and search requests until the user confirms they are done.
10
10
  )
11
- input :access_token
11
+ input :client_id,
12
+ title: 'Client ID',
13
+ description: %(
14
+ Enter the client ID you will use to connect to this CARIN server via a SMART launch.
15
+ )
16
+
12
17
  config options: { accepts_multiple_requests: true }
13
18
 
19
+ def example_client_jwt_payload_part
20
+ Base64.strict_encode64({ inferno_client_id: client_id }.to_json).delete('=')
21
+ end
22
+
14
23
  run do
15
24
  wait(
16
- identifier: access_token,
25
+ identifier: client_id,
17
26
  message: %(
18
- Access Token: #{access_token} \n
27
+ ### SMART App Launch
28
+
29
+ You may connect to the Inferno CARIN client test server via
30
+ [SMART App Launch](https://hl7.org/fhir/smart-app-launch/STU2/app-launch.html).
31
+ Perform the following steps:
32
+ 1. Perform a [Standalone Launch](https://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#step-2-launch-standalone)
33
+ 2. Retrieve .well-known/smart-configuration: `#{smart_configuration_url}`
34
+ 3. Obtain authorization code: `#{authorization_url}`
35
+ 4. Obtain access token: `#{token_url}`
36
+ 5. Access FHIR API
37
+
38
+ ### Request Identification
39
+
40
+ In order to identify requests for this session, Inferno will look for
41
+ an `Authorization` header with value:
42
+
43
+ ```
44
+ Bearer eyJhbGciOiJub25lIn0.#{example_client_jwt_payload_part}.
45
+ ```
46
+
47
+ ### FHIR API
48
+
19
49
  Submit CARIN requests via the following method:
20
50
  * Single Resource API: `#{submit_url}?:search_params`, with `:endpoint` replaced with the endpoint you want
21
51
  to reach and `:search_params` replaced with the search parameters for the request.
@@ -67,7 +97,8 @@ module CarinForBlueButtonTestKit
67
97
  * ExplanationOfBenefit:payee
68
98
  * ExplanationOfBenefit:*
69
99
 
70
- [Click here](#{resume_claims_data_url}?token=#{access_token}) when done.
100
+
101
+ [Click here](#{resume_claims_data_url}?test_run_identifier=#{client_id}) when done.
71
102
  ),
72
103
  timeout: 900
73
104
  )
@@ -23,6 +23,34 @@
23
23
  {
24
24
  "mode": "server",
25
25
  "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",
26
+ "security": {
27
+ "extension": [
28
+ {
29
+ "url": "http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris",
30
+ "extension": [
31
+ {
32
+ "url": "token",
33
+ "valueUri": "<%= Inferno::Application['base_url'] %>/custom/c4bb_v200_client/mock_auth/token"
34
+ },
35
+ {
36
+ "url": "authorize",
37
+ "valueUri": "<%= Inferno::Application['base_url'] %>/custom/c4bb_v200_client/mock_auth/authorization"
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "service": [
43
+ {
44
+ "coding": [
45
+ {
46
+ "system": "http://terminology.hl7.org/CodeSystem/restful-security-service",
47
+ "code": "SMART-on-FHIR"
48
+ }
49
+ ],
50
+ "text": "OAuth2 using SMART-on-FHIR profile (see http://docs.smarthealthit.org)"
51
+ }
52
+ ]
53
+ },
26
54
  "resource": [
27
55
  {
28
56
  "extension": [
@@ -0,0 +1,35 @@
1
+ module CarinForBlueButtonTestKit
2
+ module MockAuthorization
3
+ RSA_PRIVATE_KEY = OpenSSL::PKey::RSA.generate(2048)
4
+ RSA_PUBLIC_KEY = RSA_PRIVATE_KEY.public_key
5
+
6
+ module_function
7
+
8
+ def extract_client_id_from_bearer_token(request)
9
+ token = request.headers['authorization']&.delete_prefix('Bearer ')
10
+ jwt =
11
+ begin
12
+ JWT.decode(token, nil, false)
13
+ rescue StandardError
14
+ nil
15
+ end
16
+ jwt&.first&.dig('inferno_client_id')
17
+ end
18
+
19
+ def jwks(_env)
20
+ response_body = {
21
+ keys: [
22
+ {
23
+ kty: 'RSA',
24
+ alg: 'RS256',
25
+ n: Base64.urlsafe_encode64(RSA_PUBLIC_KEY.n.to_s(2), padding: false),
26
+ e: Base64.urlsafe_encode64(RSA_PUBLIC_KEY.e.to_s(2), padding: false),
27
+ use: 'sig'
28
+ }
29
+ ]
30
+ }.to_json
31
+
32
+ [200, { 'Content-Type' => 'application/json' }, [response_body]]
33
+ end
34
+ end
35
+ end
@@ -2,7 +2,6 @@ require_relative 'user_input_response'
2
2
  require_relative 'urls'
3
3
  require_relative 'collection'
4
4
  require_relative 'client_validation_test'
5
- # require_relative 'metadata/mock_capability_statement'
6
5
 
7
6
  module CarinForBlueButtonTestKit
8
7
  # Serve responses to CARIN requests
@@ -13,6 +12,8 @@ module CarinForBlueButtonTestKit
13
12
  module MockServer
14
13
  include URLs
15
14
 
15
+ SUPPORTED_SCOPES = ['launch', 'patient/*.rs', 'user/*.rs', 'offline_access'].freeze
16
+
16
17
  def server_proxy
17
18
  @server_proxy ||= Faraday.new(
18
19
  url: ENV.fetch('FHIR_REFERENCE_SERVER'),
@@ -25,12 +26,6 @@ module CarinForBlueButtonTestKit
25
26
  end
26
27
  end
27
28
 
28
- def token_response(request, _test = nil, _test_result = nil)
29
- # Placeholder for a more complete mock token endpoint
30
- response.body = { access_token: SecureRandom.hex, token_type: 'bearer', expires_in: 300 }.to_json
31
- response.status = 200
32
- end
33
-
34
29
  def error_response_resource(request)
35
30
  server_response = server_proxy.get('Patient', { _id: 888 })
36
31
  response_resource = FHIR.from_contents(server_response.body)
@@ -97,9 +92,43 @@ module CarinForBlueButtonTestKit
97
92
  end
98
93
 
99
94
  def get_metadata
95
+ erb_template = ERB.new(
96
+ File.read(
97
+ File.join(__dir__,
98
+ 'metadata/mock_capability_statement.json.erb')
99
+ )
100
+ )
101
+ capability_statement = JSON.parse(erb_template.result).to_json
102
+
100
103
  proc {
101
104
  [200, { 'Content-Type' => 'application/fhir+json;charset=utf-8' },
102
- [File.read('lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_capability_statement.json')]]
105
+ [capability_statement]]
106
+ }
107
+ end
108
+
109
+ def carin_smart_config
110
+ response_body =
111
+ {
112
+ authorization_endpoint: authorization_url,
113
+ token_endpoint: token_url,
114
+ token_endpoint_auth_methods_supported: ['private_key_jwt'],
115
+ token_endpoint_auth_signing_alg_values_supported: ['RS256'],
116
+ grant_types_supported: ['authorization_code'],
117
+ scopes_supported: SUPPORTED_SCOPES,
118
+ response_types_supported: ['code'],
119
+ code_challenge_methods_supported: ['S256'],
120
+ capabilities: [
121
+ 'launch-ehr',
122
+ 'permission-patient',
123
+ 'permission-user',
124
+ 'client-public',
125
+ 'client-confidential-symmetric',
126
+ 'client-confidential-asymmetric'
127
+ ]
128
+ }.to_json
129
+
130
+ proc {
131
+ [200, { 'Content-Type' => 'application/json' }, [response_body]]
103
132
  }
104
133
  end
105
134
 
@@ -137,6 +166,10 @@ module CarinForBlueButtonTestKit
137
166
  request.query_parameters['token']
138
167
  end
139
168
 
169
+ def extract_test_run_identifier_from_query_params(request)
170
+ request.query_parameters['test_run_identifier']
171
+ end
172
+
140
173
  # Pull resource type from url
141
174
  # e.g. http://example.org/fhir/Patient?_id=123 -> Patient
142
175
  # @private
@@ -156,7 +189,8 @@ module CarinForBlueButtonTestKit
156
189
 
157
190
  def mock_operation_outcome_resource
158
191
  FHIR.from_contents(File.read(
159
- 'lib/carin_for_blue_button_test_kit/client/v2.0.0/metadata/mock_operation_outcome_resource.json'
192
+ File.join(__dir__,
193
+ 'metadata/mock_operation_outcome_resource.json')
160
194
  ))
161
195
  end
162
196
 
@@ -17,7 +17,6 @@ module CarinForBlueButtonTestKit
17
17
  * _id
18
18
  * patient
19
19
  )
20
- input :access_token
21
20
 
22
21
  verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14'
23
22
 
@@ -31,7 +31,6 @@ module CarinForBlueButtonTestKit
31
31
  * ExplanationOfBenefit:payee
32
32
  * ExplanationOfBenefit:*
33
33
  )
34
- input :access_token
35
34
 
36
35
  verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14'
37
36
 
@@ -18,7 +18,6 @@ module CarinForBlueButtonTestKit
18
18
  * name
19
19
  * address
20
20
  )
21
- input :access_token
22
21
 
23
22
  verifies_requirements 'hl7.fhir.us.carin-bb_2.0.0@14'
24
23