smart_app_launch_test_kit 0.4.2 → 0.4.4

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/lib/smart_app_launch/backend_services_authorization_request_success_test.rb +3 -2
  3. data/lib/smart_app_launch/backend_services_invalid_client_assertion_test.rb +3 -2
  4. data/lib/smart_app_launch/backend_services_invalid_grant_type_test.rb +3 -2
  5. data/lib/smart_app_launch/backend_services_invalid_jwt_test.rb +3 -2
  6. data/lib/smart_app_launch/ehr_launch_group_stu2_2.rb +54 -0
  7. data/lib/smart_app_launch/smart_access_brands_examples/r4_capability_statement.json +198 -0
  8. data/lib/smart_app_launch/smart_access_brands_group.rb +59 -0
  9. data/lib/smart_app_launch/smart_access_brands_retrieval_group.rb +21 -0
  10. data/lib/smart_app_launch/smart_access_brands_retrieve_bundle_test.rb +31 -0
  11. data/lib/smart_app_launch/smart_access_brands_suite.rb +77 -0
  12. data/lib/smart_app_launch/smart_access_brands_validate_brands_test.rb +104 -0
  13. data/lib/smart_app_launch/smart_access_brands_validate_bundle_test.rb +45 -0
  14. data/lib/smart_app_launch/smart_access_brands_validate_endpoint_urls_test.rb +120 -0
  15. data/lib/smart_app_launch/smart_access_brands_validate_endpoints_test.rb +70 -0
  16. data/lib/smart_app_launch/smart_access_brands_validation_group.rb +24 -0
  17. data/lib/smart_app_launch/smart_stu2_2_suite.rb +243 -0
  18. data/lib/smart_app_launch/smart_stu2_suite.rb +5 -5
  19. data/lib/smart_app_launch/standalone_launch_group_stu2_2.rb +52 -0
  20. data/lib/smart_app_launch/token_introspection_access_token_group_stu2_2.rb +28 -0
  21. data/lib/smart_app_launch/token_introspection_group_stu2_2.rb +68 -0
  22. data/lib/smart_app_launch/token_payload_validation.rb +129 -60
  23. data/lib/smart_app_launch/token_refresh_stu2_group.rb +46 -0
  24. data/lib/smart_app_launch/token_refresh_stu2_test.rb +46 -0
  25. data/lib/smart_app_launch/token_refresh_test.rb +10 -6
  26. data/lib/smart_app_launch/token_response_body_test_stu2_2.rb +32 -0
  27. data/lib/smart_app_launch/version.rb +1 -1
  28. data/lib/smart_app_launch/well_known_endpoint_test.rb +5 -1
  29. data/lib/smart_app_launch_test_kit.rb +2 -0
  30. metadata +21 -3
@@ -5,66 +5,66 @@ module SMARTAppLaunch
5
5
 
6
6
  # All resource types from DSTU3, STU3, R4, R4B, and R5
7
7
  FHIR_RESOURCE_TYPES = [
8
- "Account", "ActivityDefinition", "ActorDefinition",
9
- "AdministrableProductDefinition", "AdverseEvent", "AllergyIntolerance",
10
- "Appointment", "AppointmentResponse", "ArtifactAssessment", "AuditEvent",
11
- "Basic", "Binary", "BiologicallyDerivedProduct",
12
- "BiologicallyDerivedProductDispense", "BodySite", "BodyStructure",
13
- "Bundle", "CapabilityStatement", "CarePlan", "CareTeam", "CatalogEntry",
14
- "ChargeItem", "ChargeItemDefinition", "Citation", "Claim",
15
- "ClaimResponse", "ClinicalImpression", "ClinicalUseDefinition",
16
- "CodeSystem", "Communication", "CommunicationRequest",
17
- "CompartmentDefinition", "Composition", "ConceptMap", "Condition",
18
- "ConditionDefinition", "Conformance", "Consent", "Contract", "Coverage",
19
- "CoverageEligibilityRequest", "CoverageEligibilityResponse",
20
- "DataElement", "DetectedIssue", "Device", "DeviceAssociation",
21
- "DeviceComponent", "DeviceDefinition", "DeviceDispense", "DeviceMetric",
22
- "DeviceRequest", "DeviceUsage", "DeviceUseRequest", "DeviceUseStatement",
23
- "DiagnosticOrder", "DiagnosticReport", "DocumentManifest",
24
- "DocumentReference", "EffectEvidenceSynthesis", "EligibilityRequest",
25
- "EligibilityResponse", "Encounter", "EncounterHistory", "Endpoint",
26
- "EnrollmentRequest", "EnrollmentResponse", "EpisodeOfCare",
27
- "EventDefinition", "Evidence", "EvidenceReport", "EvidenceVariable",
28
- "ExampleScenario", "ExpansionProfile", "ExplanationOfBenefit",
29
- "FamilyMemberHistory", "Flag", "FormularyItem", "GenomicStudy", "Goal",
30
- "GraphDefinition", "Group", "GuidanceResponse", "HealthcareService",
31
- "ImagingManifest", "ImagingObjectSelection", "ImagingSelection",
32
- "ImagingStudy", "Immunization", "ImmunizationEvaluation",
33
- "ImmunizationRecommendation", "ImplementationGuide", "Ingredient",
34
- "InsurancePlan", "InventoryItem", "InventoryReport", "Invoice", "Library",
35
- "Linkage", "List", "Location", "ManufacturedItemDefinition", "Measure",
36
- "MeasureReport", "Media", "Medication", "MedicationAdministration",
37
- "MedicationDispense", "MedicationKnowledge", "MedicationOrder",
38
- "MedicationRequest", "MedicationStatement", "MedicinalProduct",
39
- "MedicinalProductAuthorization", "MedicinalProductContraindication",
40
- "MedicinalProductDefinition", "MedicinalProductIndication",
41
- "MedicinalProductIngredient", "MedicinalProductInteraction",
42
- "MedicinalProductManufactured", "MedicinalProductPackaged",
43
- "MedicinalProductPharmaceutical", "MedicinalProductUndesirableEffect",
44
- "MessageDefinition", "MessageHeader", "MolecularSequence", "NamingSystem",
45
- "NutritionIntake", "NutritionOrder", "NutritionProduct", "Observation",
46
- "ObservationDefinition", "OperationDefinition", "OperationOutcome",
47
- "Order", "OrderResponse", "Organization", "OrganizationAffiliation",
48
- "PackagedProductDefinition", "Patient", "PaymentNotice",
49
- "PaymentReconciliation", "Permission", "Person", "PlanDefinition",
50
- "Practitioner", "PractitionerRole", "Procedure", "ProcedureRequest",
51
- "ProcessRequest", "ProcessResponse", "Provenance", "Questionnaire",
52
- "QuestionnaireResponse", "ReferralRequest", "RegulatedAuthorization",
53
- "RelatedPerson", "RequestGroup", "RequestOrchestration", "Requirements",
54
- "ResearchDefinition", "ResearchElementDefinition", "ResearchStudy",
55
- "ResearchSubject", "RiskAssessment", "RiskEvidenceSynthesis", "Schedule",
56
- "SearchParameter", "Sequence", "ServiceDefinition", "ServiceRequest",
57
- "Slot", "Specimen", "SpecimenDefinition", "StructureDefinition",
58
- "StructureMap", "Subscription", "SubscriptionStatus", "SubscriptionTopic",
59
- "Substance", "SubstanceDefinition", "SubstanceNucleicAcid",
60
- "SubstancePolymer", "SubstanceProtein", "SubstanceReferenceInformation",
61
- "SubstanceSourceMaterial", "SubstanceSpecification", "SupplyDelivery",
62
- "SupplyRequest", "Task", "TerminologyCapabilities", "TestPlan",
63
- "TestReport", "TestScript", "Transport", "ValueSet", "VerificationResult",
64
- "VisionPrescription"
8
+ 'Account', 'ActivityDefinition', 'ActorDefinition',
9
+ 'AdministrableProductDefinition', 'AdverseEvent', 'AllergyIntolerance',
10
+ 'Appointment', 'AppointmentResponse', 'ArtifactAssessment', 'AuditEvent',
11
+ 'Basic', 'Binary', 'BiologicallyDerivedProduct',
12
+ 'BiologicallyDerivedProductDispense', 'BodySite', 'BodyStructure',
13
+ 'Bundle', 'CapabilityStatement', 'CarePlan', 'CareTeam', 'CatalogEntry',
14
+ 'ChargeItem', 'ChargeItemDefinition', 'Citation', 'Claim',
15
+ 'ClaimResponse', 'ClinicalImpression', 'ClinicalUseDefinition',
16
+ 'CodeSystem', 'Communication', 'CommunicationRequest',
17
+ 'CompartmentDefinition', 'Composition', 'ConceptMap', 'Condition',
18
+ 'ConditionDefinition', 'Conformance', 'Consent', 'Contract', 'Coverage',
19
+ 'CoverageEligibilityRequest', 'CoverageEligibilityResponse',
20
+ 'DataElement', 'DetectedIssue', 'Device', 'DeviceAssociation',
21
+ 'DeviceComponent', 'DeviceDefinition', 'DeviceDispense', 'DeviceMetric',
22
+ 'DeviceRequest', 'DeviceUsage', 'DeviceUseRequest', 'DeviceUseStatement',
23
+ 'DiagnosticOrder', 'DiagnosticReport', 'DocumentManifest',
24
+ 'DocumentReference', 'EffectEvidenceSynthesis', 'EligibilityRequest',
25
+ 'EligibilityResponse', 'Encounter', 'EncounterHistory', 'Endpoint',
26
+ 'EnrollmentRequest', 'EnrollmentResponse', 'EpisodeOfCare',
27
+ 'EventDefinition', 'Evidence', 'EvidenceReport', 'EvidenceVariable',
28
+ 'ExampleScenario', 'ExpansionProfile', 'ExplanationOfBenefit',
29
+ 'FamilyMemberHistory', 'Flag', 'FormularyItem', 'GenomicStudy', 'Goal',
30
+ 'GraphDefinition', 'Group', 'GuidanceResponse', 'HealthcareService',
31
+ 'ImagingManifest', 'ImagingObjectSelection', 'ImagingSelection',
32
+ 'ImagingStudy', 'Immunization', 'ImmunizationEvaluation',
33
+ 'ImmunizationRecommendation', 'ImplementationGuide', 'Ingredient',
34
+ 'InsurancePlan', 'InventoryItem', 'InventoryReport', 'Invoice', 'Library',
35
+ 'Linkage', 'List', 'Location', 'ManufacturedItemDefinition', 'Measure',
36
+ 'MeasureReport', 'Media', 'Medication', 'MedicationAdministration',
37
+ 'MedicationDispense', 'MedicationKnowledge', 'MedicationOrder',
38
+ 'MedicationRequest', 'MedicationStatement', 'MedicinalProduct',
39
+ 'MedicinalProductAuthorization', 'MedicinalProductContraindication',
40
+ 'MedicinalProductDefinition', 'MedicinalProductIndication',
41
+ 'MedicinalProductIngredient', 'MedicinalProductInteraction',
42
+ 'MedicinalProductManufactured', 'MedicinalProductPackaged',
43
+ 'MedicinalProductPharmaceutical', 'MedicinalProductUndesirableEffect',
44
+ 'MessageDefinition', 'MessageHeader', 'MolecularSequence', 'NamingSystem',
45
+ 'NutritionIntake', 'NutritionOrder', 'NutritionProduct', 'Observation',
46
+ 'ObservationDefinition', 'OperationDefinition', 'OperationOutcome',
47
+ 'Order', 'OrderResponse', 'Organization', 'OrganizationAffiliation',
48
+ 'PackagedProductDefinition', 'Patient', 'PaymentNotice',
49
+ 'PaymentReconciliation', 'Permission', 'Person', 'PlanDefinition',
50
+ 'Practitioner', 'PractitionerRole', 'Procedure', 'ProcedureRequest',
51
+ 'ProcessRequest', 'ProcessResponse', 'Provenance', 'Questionnaire',
52
+ 'QuestionnaireResponse', 'ReferralRequest', 'RegulatedAuthorization',
53
+ 'RelatedPerson', 'RequestGroup', 'RequestOrchestration', 'Requirements',
54
+ 'ResearchDefinition', 'ResearchElementDefinition', 'ResearchStudy',
55
+ 'ResearchSubject', 'RiskAssessment', 'RiskEvidenceSynthesis', 'Schedule',
56
+ 'SearchParameter', 'Sequence', 'ServiceDefinition', 'ServiceRequest',
57
+ 'Slot', 'Specimen', 'SpecimenDefinition', 'StructureDefinition',
58
+ 'StructureMap', 'Subscription', 'SubscriptionStatus', 'SubscriptionTopic',
59
+ 'Substance', 'SubstanceDefinition', 'SubstanceNucleicAcid',
60
+ 'SubstancePolymer', 'SubstanceProtein', 'SubstanceReferenceInformation',
61
+ 'SubstanceSourceMaterial', 'SubstanceSpecification', 'SupplyDelivery',
62
+ 'SupplyRequest', 'Task', 'TerminologyCapabilities', 'TestPlan',
63
+ 'TestReport', 'TestScript', 'Transport', 'ValueSet', 'VerificationResult',
64
+ 'VisionPrescription'
65
65
  ].to_set.freeze
66
66
 
67
- FHIR_ID_REGEX = /[A-Za-z0-9\-\.]{1,64}(\/_history\/[A-Za-z0-9\-\.]{1,64})?(#[A-Za-z0-9\-\.]{1,64})?/.freeze
67
+ FHIR_ID_REGEX = %r{[A-Za-z0-9\-\.]{1,64}(/_history/[A-Za-z0-9\-\.]{1,64})?(#[A-Za-z0-9\-\.]{1,64})?}
68
68
 
69
69
  def validate_required_fields_present(body, required_fields)
70
70
  missing_fields = required_fields.select { |field| body[field].blank? }
@@ -93,7 +93,7 @@ module SMARTAppLaunch
93
93
 
94
94
  def validate_scope_subset(received_scopes, original_scopes)
95
95
  extra_scopes = received_scopes.split - original_scopes.split
96
- assert extra_scopes.empty?, "Token response contained scopes which are not a subset of the scope granted to the "\
96
+ assert extra_scopes.empty?, 'Token response contained scopes which are not a subset of the scope granted to the ' \
97
97
  "original access token: #{extra_scopes.join(', ')}"
98
98
  end
99
99
 
@@ -124,7 +124,6 @@ module SMARTAppLaunch
124
124
 
125
125
  fhir_context.each do |reference|
126
126
  assert !reference.start_with?('http'), "`#{reference}` is not a relative reference"
127
-
128
127
  resource_type, id = reference.split('/')
129
128
  assert FHIR_RESOURCE_TYPES.include?(resource_type),
130
129
  "`#{resource_type}` is not a valid FHIR resource type"
@@ -132,5 +131,75 @@ module SMARTAppLaunch
132
131
  assert id.match?(FHIR_ID_REGEX), "`#{id}` is not a valid FHIR id"
133
132
  end
134
133
  end
134
+
135
+ def check_fhir_context_reference(reference)
136
+ assert reference.is_a?(String), "`#{reference.inspect}` is not a String"
137
+ assert !reference.start_with?('http'), "`#{reference}` is not a relative reference"
138
+
139
+ resource_type, id = reference.split('/')
140
+
141
+ assert FHIR_RESOURCE_TYPES.include?(resource_type),
142
+ "`#{resource_type}` in `reference` is not a valid FHIR resource type"
143
+
144
+ assert id.match?(FHIR_ID_REGEX), "`#{id}` in `reference` is not a valid FHIR id"
145
+ end
146
+
147
+ def check_fhir_context_canonical(canonical)
148
+ assert canonical.is_a?(String), "`#{canonical.inspect}` is not a String"
149
+ assert canonical.start_with?('http'), "`#{canonical}` is not a canonical reference"
150
+
151
+ split_canonical = canonical.split('/')
152
+
153
+ if split_canonical.last.start_with?(/&|\|/)
154
+ resource_type = split_canonical[-3]
155
+ id = split_canonical[-2]
156
+ else
157
+ resource_type = split_canonical[-2]
158
+ id = split_canonical.last.split(/&|\|/).first
159
+ end
160
+
161
+ assert FHIR_RESOURCE_TYPES.include?(resource_type),
162
+ "`#{resource_type}` in `canonical` is not a valid FHIR resource type"
163
+
164
+ assert id.match?(FHIR_ID_REGEX), "`#{id}` in `canonical` is not a valid FHIR id"
165
+ end
166
+
167
+ def check_fhir_context_identifier(identifier)
168
+ assert identifier.is_a?(Hash), "`#{identifier.inspect}` is not an Object"
169
+ end
170
+
171
+ def validate_fhir_context_stu2_2(fhir_context)
172
+ return if fhir_context.nil?
173
+
174
+ assert fhir_context.is_a?(Array), "`fhirContext` field is a #{fhir_context.class.name}, but should be an Array"
175
+
176
+ fhir_context.each do |reference|
177
+ assert reference.is_a?(Hash), "`#{reference.inspect}` is not an Object"
178
+ end
179
+
180
+ fhir_context.each do |context|
181
+ reference = context['reference']
182
+ canonical = context['canonical']
183
+ identifier = context['identifier']
184
+
185
+ type = context['type']
186
+
187
+ assert reference.present? || canonical.present? || identifier.present?,
188
+ '`fhirContext` array SHALL include at least one of "reference", "canonical", or "identifier"'
189
+
190
+ check_fhir_context_reference(reference) if reference.present?
191
+ check_fhir_context_canonical(canonical) if canonical.present?
192
+ check_fhir_context_identifier(identifier) if identifier.present?
193
+
194
+ if (canonical.present? || identifier.present?) && type.blank?
195
+ info 'The `type` field is recommended when "canonical" or "identifier" is present in `fhirContext` object'
196
+ end
197
+
198
+ next unless type.present?
199
+
200
+ assert FHIR_RESOURCE_TYPES.include?(type),
201
+ "`#{type}` in `type` is not a valid FHIR resource type"
202
+ end
203
+ end
135
204
  end
136
205
  end
@@ -0,0 +1,46 @@
1
+ require_relative 'token_refresh_stu2_test'
2
+ require_relative 'token_refresh_body_test'
3
+ require_relative 'token_response_headers_test'
4
+
5
+ module SMARTAppLaunch
6
+ class TokenRefreshSTU2Group < Inferno::TestGroup
7
+ id :smart_token_refresh_stu2
8
+ title 'SMART Token Refresh'
9
+ short_description 'Demonstrate the ability to exchange a refresh token for an access token.'
10
+ description %(
11
+ # Background
12
+
13
+ The #{title} Sequence tests the ability of the system to successfully
14
+ exchange a refresh token for an access token. Refresh tokens are typically
15
+ longer lived than access tokens and allow client applications to obtain a
16
+ new access token Refresh tokens themselves cannot provide access to
17
+ resources on the server.
18
+
19
+ Token refreshes are accomplished through a `POST` request to the token
20
+ exchange endpoint as described in the [SMART App Launch
21
+ Framework](https://www.hl7.org/fhir/smart-app-launch/1.0.0/index.html#step-5-later-app-uses-a-refresh-token-to-obtain-a-new-access-token).
22
+
23
+ # Test Methodology
24
+
25
+ This test attempts to exchange the refresh token for a new access token
26
+ and verify that the information returned contains the required fields and
27
+ uses the proper headers.
28
+
29
+ For more information see:
30
+
31
+ * [The OAuth 2.0 Authorization
32
+ Framework](https://tools.ietf.org/html/rfc6749)
33
+ * [Using a refresh token to obtain a new access
34
+ token](https://www.hl7.org/fhir/smart-app-launch/1.0.0/index.html#step-5-later-app-uses-a-refresh-token-to-obtain-a-new-access-token)
35
+ )
36
+
37
+ test from: :smart_token_refresh_stu2
38
+ test from: :smart_token_refresh_body
39
+ test from: :smart_token_response_headers,
40
+ config: {
41
+ requests: {
42
+ token: { name: :token_refresh }
43
+ }
44
+ }
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ require_relative 'token_refresh_test'
2
+
3
+ module SMARTAppLaunch
4
+ class TokenRefreshSTU2Test < TokenRefreshTest
5
+ include TokenPayloadValidation
6
+
7
+ id :smart_token_refresh_stu2
8
+ title 'Server successfully refreshes the access token when optional scope parameter omitted'
9
+ description %(
10
+ Server successfully exchanges refresh token at OAuth token endpoint
11
+ without providing scope in the body of the request.
12
+
13
+ Although not required in the token refresh portion of the SMART App
14
+ Launch Guide, the token refresh response should include the HTTP
15
+ Cache-Control response header field with a value of no-store, as well as
16
+ the Pragma response header field with a value of no-cache to be
17
+ consistent with the requirements of the inital access token exchange.
18
+ )
19
+ input :client_auth_type
20
+ input :client_auth_encryption_method, optional: true
21
+ input :client_secret, optional: true
22
+
23
+ def add_credentials_to_request(oauth2_headers, oauth2_params)
24
+ case client_auth_type
25
+ when 'public'
26
+ oauth2_params['client_id'] = client_id
27
+ when 'confidential_symmetric'
28
+ assert client_secret.present?,
29
+ "A client secret must be provided when using confidential symmetric client authentication."
30
+
31
+ credentials = Base64.strict_encode64("#{client_id}:#{client_secret}")
32
+ oauth2_headers['Authorization'] = "Basic #{credentials}"
33
+ when 'confidential_asymmetric'
34
+ oauth2_params.merge!(
35
+ client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
36
+ client_assertion: ClientAssertionBuilder.build(
37
+ iss: client_id,
38
+ sub: client_id,
39
+ aud: smart_token_url,
40
+ client_auth_encryption_method: client_auth_encryption_method
41
+ )
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
@@ -21,6 +21,15 @@ module SMARTAppLaunch
21
21
  output :smart_credentials, :token_retrieval_time
22
22
  makes_request :token_refresh
23
23
 
24
+ def add_credentials_to_request(oauth2_headers, oauth2_params)
25
+ if client_secret.present?
26
+ credentials = Base64.strict_encode64("#{client_id}:#{client_secret}")
27
+ oauth2_headers['Authorization'] = "Basic #{credentials}"
28
+ else
29
+ oauth2_params['client_id'] = client_id
30
+ end
31
+ end
32
+
24
33
  run do
25
34
  skip_if refresh_token.blank?
26
35
 
@@ -32,12 +41,7 @@ module SMARTAppLaunch
32
41
 
33
42
  oauth2_params['scope'] = received_scopes if config.options[:include_scopes]
34
43
 
35
- if client_secret.present?
36
- credentials = Base64.strict_encode64("#{client_id}:#{client_secret}")
37
- oauth2_headers['Authorization'] = "Basic #{credentials}"
38
- else
39
- oauth2_params['client_id'] = client_id
40
- end
44
+ add_credentials_to_request(oauth2_headers, oauth2_params)
41
45
 
42
46
  post(smart_token_url, body: oauth2_params, name: :token_refresh, headers: oauth2_headers)
43
47
 
@@ -0,0 +1,32 @@
1
+ require_relative 'token_payload_validation'
2
+
3
+ module SMARTAppLaunch
4
+ class TokenResponseBodyTestSTU22 < TokenResponseBodyTest
5
+ title 'Token exchange response body contains required information encoded in JSON'
6
+ description %(
7
+ The EHR authorization server shall return a JSON structure that includes
8
+ an access token or a message indicating that the authorization request
9
+ has been denied. `access_token`, `token_type`, and `scope` are required.
10
+ `token_type` must be Bearer. `expires_in` is required for token
11
+ refreshes.
12
+
13
+ The format of the optional `fhirContext` field is validated if present.
14
+ )
15
+ id :smart_token_response_body_stu2_2
16
+
17
+ input :requested_scopes
18
+ output :id_token,
19
+ :refresh_token,
20
+ :access_token,
21
+ :expires_in,
22
+ :patient_id,
23
+ :encounter_id,
24
+ :received_scopes,
25
+ :intent
26
+ uses_request :token
27
+
28
+ def validate_fhir_context(fhir_context)
29
+ validate_fhir_context_stu2_2(fhir_context)
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,3 @@
1
1
  module SMARTAppLaunch
2
- VERSION = '0.4.2'.freeze
2
+ VERSION = '0.4.4'.freeze
3
3
  end
@@ -13,6 +13,7 @@ module SMARTAppLaunch
13
13
  input :url,
14
14
  title: 'FHIR Endpoint',
15
15
  description: 'URL of the FHIR endpoint used by SMART applications'
16
+
16
17
  output :well_known_configuration,
17
18
  :well_known_authorization_url,
18
19
  :well_known_introspection_url,
@@ -34,9 +35,12 @@ module SMARTAppLaunch
34
35
  base_url = "#{url.chomp('/')}/"
35
36
  config = JSON.parse(request.response_body)
36
37
 
38
+ if config['introspection_endpoint'].present?
39
+ output well_known_introspection_url: make_url_absolute(base_url, config['introspection_endpoint'])
40
+ end
41
+
37
42
  output well_known_configuration: request.response_body,
38
43
  well_known_authorization_url: make_url_absolute(base_url, config['authorization_endpoint']),
39
- well_known_introspection_url: make_url_absolute(base_url, config['introspection_endpoint']),
40
44
  well_known_management_url: make_url_absolute(base_url, config['management_endpoint']),
41
45
  well_known_registration_url: make_url_absolute(base_url, config['registration_endpoint']),
42
46
  well_known_revocation_url: make_url_absolute(base_url, config['revocation_endpoint']),
@@ -2,3 +2,5 @@ require 'tls_test_kit'
2
2
 
3
3
  require_relative 'smart_app_launch/smart_stu1_suite'
4
4
  require_relative 'smart_app_launch/smart_stu2_suite'
5
+ require_relative 'smart_app_launch/smart_stu2_2_suite'
6
+ require_relative 'smart_app_launch/smart_access_brands_suite'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_app_launch_test_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen MacVicar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-25 00:00:00.000000000 Z
11
+ date: 2024-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: inferno_core
@@ -161,6 +161,7 @@ files:
161
161
  - lib/smart_app_launch/discovery_stu2_group.rb
162
162
  - lib/smart_app_launch/ehr_launch_group.rb
163
163
  - lib/smart_app_launch/ehr_launch_group_stu2.rb
164
+ - lib/smart_app_launch/ehr_launch_group_stu2_2.rb
164
165
  - lib/smart_app_launch/jwks.rb
165
166
  - lib/smart_app_launch/launch_received_test.rb
166
167
  - lib/smart_app_launch/openid_connect_group.rb
@@ -172,22 +173,39 @@ files:
172
173
  - lib/smart_app_launch/openid_token_header_test.rb
173
174
  - lib/smart_app_launch/openid_token_payload_test.rb
174
175
  - lib/smart_app_launch/post_auth.html
176
+ - lib/smart_app_launch/smart_access_brands_examples/r4_capability_statement.json
177
+ - lib/smart_app_launch/smart_access_brands_group.rb
178
+ - lib/smart_app_launch/smart_access_brands_retrieval_group.rb
179
+ - lib/smart_app_launch/smart_access_brands_retrieve_bundle_test.rb
180
+ - lib/smart_app_launch/smart_access_brands_suite.rb
181
+ - lib/smart_app_launch/smart_access_brands_validate_brands_test.rb
182
+ - lib/smart_app_launch/smart_access_brands_validate_bundle_test.rb
183
+ - lib/smart_app_launch/smart_access_brands_validate_endpoint_urls_test.rb
184
+ - lib/smart_app_launch/smart_access_brands_validate_endpoints_test.rb
185
+ - lib/smart_app_launch/smart_access_brands_validation_group.rb
175
186
  - lib/smart_app_launch/smart_jwks.json
176
187
  - lib/smart_app_launch/smart_stu1_suite.rb
188
+ - lib/smart_app_launch/smart_stu2_2_suite.rb
177
189
  - lib/smart_app_launch/smart_stu2_suite.rb
178
190
  - lib/smart_app_launch/standalone_launch_group.rb
179
191
  - lib/smart_app_launch/standalone_launch_group_stu2.rb
192
+ - lib/smart_app_launch/standalone_launch_group_stu2_2.rb
180
193
  - lib/smart_app_launch/token_exchange_stu2_test.rb
181
194
  - lib/smart_app_launch/token_exchange_test.rb
182
195
  - lib/smart_app_launch/token_introspection_access_token_group.rb
196
+ - lib/smart_app_launch/token_introspection_access_token_group_stu2_2.rb
183
197
  - lib/smart_app_launch/token_introspection_group.rb
198
+ - lib/smart_app_launch/token_introspection_group_stu2_2.rb
184
199
  - lib/smart_app_launch/token_introspection_request_group.rb
185
200
  - lib/smart_app_launch/token_introspection_response_group.rb
186
201
  - lib/smart_app_launch/token_payload_validation.rb
187
202
  - lib/smart_app_launch/token_refresh_body_test.rb
188
203
  - lib/smart_app_launch/token_refresh_group.rb
204
+ - lib/smart_app_launch/token_refresh_stu2_group.rb
205
+ - lib/smart_app_launch/token_refresh_stu2_test.rb
189
206
  - lib/smart_app_launch/token_refresh_test.rb
190
207
  - lib/smart_app_launch/token_response_body_test.rb
208
+ - lib/smart_app_launch/token_response_body_test_stu2_2.rb
191
209
  - lib/smart_app_launch/token_response_headers_test.rb
192
210
  - lib/smart_app_launch/url_helpers.rb
193
211
  - lib/smart_app_launch/version.rb
@@ -216,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
216
234
  - !ruby/object:Gem::Version
217
235
  version: '0'
218
236
  requirements: []
219
- rubygems_version: 3.3.7
237
+ rubygems_version: 3.5.9
220
238
  signing_key:
221
239
  specification_version: 4
222
240
  summary: Inferno Tests for the SMART Application Launch Framework Implementation Guide