smart_app_launch_test_kit 0.4.2 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
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