onc_certification_g10_test_kit 5.4.2 → 6.0.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.
- checksums.yaml +4 -4
- data/lib/onc_certification_g10_test_kit/base_token_refresh_stu2_group.rb +49 -0
- data/lib/onc_certification_g10_test_kit/multi_patient_api_stu1.rb +13 -8
- data/lib/onc_certification_g10_test_kit/multi_patient_api_stu2.rb +12 -7
- data/lib/onc_certification_g10_test_kit/onc_program_procedure.yml +448 -468
- data/lib/onc_certification_g10_test_kit/short_id_map.yml +227 -17
- data/lib/onc_certification_g10_test_kit/single_patient_api_group.rb +6 -1
- data/lib/onc_certification_g10_test_kit/single_patient_us_core_4_api_group.rb +6 -1
- data/lib/onc_certification_g10_test_kit/single_patient_us_core_6_api_group.rb +8 -5
- data/lib/onc_certification_g10_test_kit/smart_app_launch_invalid_aud_group.rb +16 -17
- data/lib/onc_certification_g10_test_kit/smart_asymmetric_launch_group.rb +194 -0
- data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group.rb +2 -4
- data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group_stu2.rb +7 -6
- data/lib/onc_certification_g10_test_kit/smart_ehr_practitioner_app_group.rb +23 -7
- data/lib/onc_certification_g10_test_kit/smart_fine_grained_scopes_group.rb +188 -0
- data/lib/onc_certification_g10_test_kit/smart_granular_scope_selection_group.rb +150 -0
- data/lib/onc_certification_g10_test_kit/smart_granular_scope_selection_test.rb +53 -0
- data/lib/onc_certification_g10_test_kit/smart_invalid_pkce_group.rb +6 -7
- data/lib/onc_certification_g10_test_kit/smart_invalid_token_group.rb +8 -10
- data/lib/onc_certification_g10_test_kit/smart_invalid_token_group_stu2.rb +7 -9
- data/lib/onc_certification_g10_test_kit/smart_limited_app_group.rb +5 -3
- data/lib/onc_certification_g10_test_kit/smart_public_standalone_launch_group.rb +14 -16
- data/lib/onc_certification_g10_test_kit/smart_public_standalone_launch_group_stu2.rb +28 -4
- data/lib/onc_certification_g10_test_kit/smart_scopes_test.rb +34 -25
- data/lib/onc_certification_g10_test_kit/smart_standalone_patient_app_group.rb +20 -9
- data/lib/onc_certification_g10_test_kit/smart_v1_scopes_group.rb +241 -0
- data/lib/onc_certification_g10_test_kit/tasks/generate_matrix.rb +75 -51
- data/lib/onc_certification_g10_test_kit/token_introspection_group.rb +110 -0
- data/lib/onc_certification_g10_test_kit/token_revocation_group.rb +1 -1
- data/lib/onc_certification_g10_test_kit/version.rb +1 -1
- data/lib/onc_certification_g10_test_kit/visual_inspection_and_attestations_group.rb +57 -37
- data/lib/onc_certification_g10_test_kit.rb +84 -18
- metadata +13 -6
@@ -26,19 +26,33 @@ module ONCCertificationG10TestKit
|
|
26
26
|
)
|
27
27
|
|
28
28
|
description %(
|
29
|
-
|
29
|
+
This scenario verifies the ability of a system to perform a single EHR
|
30
|
+
Launch. Specifically, this scenario performs an EHR launch to a SMART on FHIR
|
30
31
|
confidential client with patient context, refresh token, OpenID Connect
|
31
32
|
(OIDC) identity token, and (SMART v2 only) use the POST HTTP method for
|
32
|
-
code exchange.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
code exchange.
|
34
|
+
|
35
|
+
After launch, a simple Patient resource read is performed on the patient
|
36
|
+
in context. The access token is then refreshed, and the Patient resource
|
37
|
+
is read using the new access token to ensure that the refresh was
|
38
|
+
successful. Finally, the authentication information provided by OpenID
|
39
|
+
Connect is decoded and validated.
|
40
|
+
|
41
|
+
Prior to running this scenario, register Inferno as an EHR-launched confidential
|
42
|
+
client with the following information:
|
43
|
+
|
44
|
+
Prior to running this test, register Inferno as an EHR-launched
|
45
|
+
application using the following information:
|
46
|
+
|
47
|
+
* Launch URI: `#{SMARTAppLaunch::AppLaunchTest.config.options[:launch_uri]}`
|
48
|
+
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
37
49
|
|
38
50
|
For EHRs that use Internet Explorer 11 to display embedded apps,
|
39
51
|
please review [instructions on how to complete the EHR Practitioner App
|
40
52
|
test](https://github.com/onc-healthit/onc-certification-g10-test-kit/wiki/Completing-EHR-Practitioner-App-test-in-Internet-Explorer/).
|
41
53
|
|
54
|
+
The following implementation specifications are relevant to this scenario:
|
55
|
+
|
42
56
|
* [SMART on FHIR
|
43
57
|
(STU1)](http://www.hl7.org/fhir/smart-app-launch/1.0.0/)
|
44
58
|
* [SMART on FHIR
|
@@ -100,6 +114,7 @@ module ONCCertificationG10TestKit
|
|
100
114
|
required_capabilities: [
|
101
115
|
'launch-ehr',
|
102
116
|
'client-confidential-symmetric',
|
117
|
+
'client-confidential-asymmetric',
|
103
118
|
'sso-openid-connect',
|
104
119
|
'context-banner',
|
105
120
|
'context-style',
|
@@ -107,7 +122,8 @@ module ONCCertificationG10TestKit
|
|
107
122
|
'permission-offline',
|
108
123
|
'permission-user',
|
109
124
|
'authorize-post',
|
110
|
-
'permission-v2'
|
125
|
+
'permission-v2',
|
126
|
+
'permission-v1'
|
111
127
|
]
|
112
128
|
}
|
113
129
|
}
|
@@ -0,0 +1,188 @@
|
|
1
|
+
module ONCCertificationG10TestKit
|
2
|
+
class SmartFineGrainedScopesGroup < USCoreTestKit::USCoreV610::SmartGranularScopesGroup
|
3
|
+
title 'SMART App Launch with fine-grained scopes'
|
4
|
+
short_title 'SMART Launch with Fine-Grained Scopes'
|
5
|
+
|
6
|
+
input_instructions %(
|
7
|
+
If necessary, register Inferno as a standalone application using the following information:
|
8
|
+
|
9
|
+
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
10
|
+
|
11
|
+
Inferno may be registered multiple times with different `client_ids`, or this
|
12
|
+
may reuse a single registration of Inferno.`
|
13
|
+
|
14
|
+
This test will perform two launches, with each launch requiring a separate
|
15
|
+
separate set of finer-grained scopes to be granted:
|
16
|
+
|
17
|
+
Group 1:
|
18
|
+
* `Condition.rs?category=http://terminology.hl7.org/CodeSystem/condition-category|encounter-diagnosis`
|
19
|
+
* `Condition.rs?category=http://hl7.org/fhir/us/core/CodeSystem/condition-category|health-concern`
|
20
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|laboratory`
|
21
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|social-history`
|
22
|
+
|
23
|
+
Group 2:
|
24
|
+
* `Condition.rs?category=http://terminology.hl7.org/CodeSystem/condition-category|problem-list-item`
|
25
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|vital-signs`
|
26
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|survey`
|
27
|
+
* `Observation.rs?category=http://hl7.org/fhir/us/core/CodeSystem/us-core-category|sdoh`
|
28
|
+
)
|
29
|
+
|
30
|
+
description <<~DESCRIPTION
|
31
|
+
|
32
|
+
As finalized in the [HTI-1 Final Rule](https://www.federalregister.gov/d/2023-28857/p-1250), Health IT Modules are
|
33
|
+
required to support SMART App Launch v2.0.0 "Finer-grained resource
|
34
|
+
constraints using search parameters" for the "category" parameter for the
|
35
|
+
Condition resource with Condition sub-resources Encounter Diagnosis, Problem
|
36
|
+
List, and Health Concern, and the Observation resource with Observation
|
37
|
+
sub-resources Clinical Test, Laboratory, Social History, SDOH, Survey, and
|
38
|
+
Vital Signs.
|
39
|
+
|
40
|
+
This is also reflected in the (g)(10) Standardized API for patient and
|
41
|
+
populations [Test
|
42
|
+
Procedure](https://www.healthit.gov/test-method/standardized-api-patient-and-population-services#test_procedure):
|
43
|
+
|
44
|
+
> [AUT-PAT-28] SMART v2 scope syntax for patient-level and user-level scopes to support
|
45
|
+
the “permission-v2” “SMART on FHIR® Capability”, including support for
|
46
|
+
finer-grained resource constraints using search parameters according to
|
47
|
+
section 3.0.2.3 of the implementation specification at § 170.215(c)(2) for
|
48
|
+
the “category” parameter for the following resources: (1) Condition
|
49
|
+
resource with Condition sub-resources Encounter Diagnosis, Problem List,
|
50
|
+
and Health Concern; and (2) Observation resource with Observation
|
51
|
+
sub-resources Clinical Test, Laboratory, Social History, SDOH, Survey, and
|
52
|
+
Vital Signs
|
53
|
+
|
54
|
+
Prior to running this scenario, first run the Single Patient API tests using
|
55
|
+
resource-level scopes, as this scenario uses content saved from that scenario
|
56
|
+
as a baseline for comparison when finer-grained scopes are granted.
|
57
|
+
|
58
|
+
This scenario contains two groups of finer-grained scope tests, each of
|
59
|
+
which includes a SMART Standalone Launch that requests a subset of
|
60
|
+
finer-grained scopes, followed by FHIR API requests to verify that scopes
|
61
|
+
are appropriately granted. The app launches require that the subset of the
|
62
|
+
requested finer-grained scopes are granted by the user. The FHIR API tests then repeat all
|
63
|
+
of the queries from the original Single Patient API tests that were run
|
64
|
+
using resource-level scopes, and verify that only resources matching the
|
65
|
+
current finer-grained scopes are returned. Each group requires a separate
|
66
|
+
set of finer-grained scopes to be granted:
|
67
|
+
|
68
|
+
Group 1:
|
69
|
+
* `Condition.rs?category=http://terminology.hl7.org/CodeSystem/condition-category|encounter-diagnosis`
|
70
|
+
* `Condition.rs?category=http://hl7.org/fhir/us/core/CodeSystem/condition-category|health-concern`
|
71
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|laboratory`
|
72
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|social-history`
|
73
|
+
|
74
|
+
Group 2:
|
75
|
+
* `Condition.rs?category=http://terminology.hl7.org/CodeSystem/condition-category|problem-list-item`
|
76
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|vital-signs`
|
77
|
+
* `Observation.rs?category=http://terminology.hl7.org/CodeSystem/observation-category|survey`
|
78
|
+
* `Observation.rs?category=http://hl7.org/fhir/us/core/CodeSystem/us-core-category|sdoh`
|
79
|
+
|
80
|
+
Note that Inferno will only request the finer grained scopes in each case,
|
81
|
+
but the system under test can display more scopes to the tester during
|
82
|
+
authorization. In this case, it is expected that the tester will only
|
83
|
+
approve the appropriate scopes in each group as described above.
|
84
|
+
|
85
|
+
For more information, please refer to [finer-grained resource constraints
|
86
|
+
using search
|
87
|
+
parameters](https://hl7.org/fhir/smart-app-launch/STU2/scopes-and-launch-context.html#finer-grained-resource-constraints-using-search-parameters).
|
88
|
+
|
89
|
+
DESCRIPTION
|
90
|
+
|
91
|
+
id :g10_smart_fine_grained_scopes
|
92
|
+
|
93
|
+
input :url
|
94
|
+
|
95
|
+
children.each(&:run_as_group)
|
96
|
+
|
97
|
+
# Replace generic finer-grained scope auth group with which allows standalone or
|
98
|
+
# ehr launch with just the standalone launch group
|
99
|
+
granular_scopes_group1 = children.first
|
100
|
+
granular_scopes_group1.children[0] = granular_scopes_group1.children.first.children.first
|
101
|
+
standalone_launch_group1 = granular_scopes_group1.children[0]
|
102
|
+
standalone_launch_group1.required
|
103
|
+
|
104
|
+
granular_scopes_group2 = children.last
|
105
|
+
granular_scopes_group2.children[0] = granular_scopes_group2.children.first.children.first
|
106
|
+
standalone_launch_group2 = granular_scopes_group2.children[0]
|
107
|
+
standalone_launch_group2.required
|
108
|
+
|
109
|
+
# Move the granular scope API groups to the top level
|
110
|
+
api_group1 = granular_scopes_group1.children.pop
|
111
|
+
api_group1.children.each do |group|
|
112
|
+
group.children.select!(&:required?)
|
113
|
+
granular_scopes_group1.children << group
|
114
|
+
end
|
115
|
+
|
116
|
+
api_group2 = granular_scopes_group2.children.pop
|
117
|
+
api_group2.children.each do |group|
|
118
|
+
group.children.select!(&:required?)
|
119
|
+
granular_scopes_group2.children << group
|
120
|
+
end
|
121
|
+
|
122
|
+
# Remove OIDC and refresh token tests
|
123
|
+
standalone_launch_group1.children.pop(2)
|
124
|
+
standalone_launch_group2.children.pop(2)
|
125
|
+
|
126
|
+
config(
|
127
|
+
inputs: {
|
128
|
+
authorization_method: {
|
129
|
+
name: :granular_scopes_authorization_method,
|
130
|
+
title: 'Granular Scopes Authorization Request Method'
|
131
|
+
},
|
132
|
+
client_auth_type: {
|
133
|
+
name: :granular_scopes_client_auth_type,
|
134
|
+
title: 'Granular Scopes Client Authentication Type'
|
135
|
+
},
|
136
|
+
received_scopes: {
|
137
|
+
name: :standalone_received_scopes
|
138
|
+
}
|
139
|
+
}
|
140
|
+
)
|
141
|
+
|
142
|
+
granular_scopes_group1.config(
|
143
|
+
inputs: {
|
144
|
+
client_id: {
|
145
|
+
name: :granular_scopes1_client_id,
|
146
|
+
title: 'Granular Scopes Group 1 Client ID'
|
147
|
+
},
|
148
|
+
client_secret: {
|
149
|
+
name: :granular_scopes1_client_secret,
|
150
|
+
title: 'Granular Scopes Group 1 Client Secret'
|
151
|
+
},
|
152
|
+
requested_scopes: {
|
153
|
+
title: 'Granular Scopes Group 1 Scopes'
|
154
|
+
}
|
155
|
+
}
|
156
|
+
)
|
157
|
+
|
158
|
+
granular_scopes_group2.config(
|
159
|
+
inputs: {
|
160
|
+
client_id: {
|
161
|
+
name: :granular_scopes2_client_id,
|
162
|
+
title: 'Granular Scopes Group 2 Client ID'
|
163
|
+
},
|
164
|
+
client_secret: {
|
165
|
+
name: :granular_scopes2_client_secret,
|
166
|
+
title: 'Granular Scopes Group 2 Client Secret'
|
167
|
+
},
|
168
|
+
requested_scopes: {
|
169
|
+
title: 'Granular Scopes Group 2 Scopes'
|
170
|
+
}
|
171
|
+
}
|
172
|
+
)
|
173
|
+
|
174
|
+
input_order :url,
|
175
|
+
:granular_scopes1_client_id,
|
176
|
+
:requested_scopes_group1,
|
177
|
+
:granular_scopes_authorization_method,
|
178
|
+
:granular_scopes_client_auth_type,
|
179
|
+
:granular_scopes1_client_secret,
|
180
|
+
:client_auth_encryption_method,
|
181
|
+
:granular_scopes2_client_id,
|
182
|
+
:requested_scopes_group2,
|
183
|
+
:granular_scopes2_client_secret,
|
184
|
+
:use_pkce,
|
185
|
+
:pkce_code_challenge_method,
|
186
|
+
:patient_ids
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require_relative 'smart_scopes_test'
|
2
|
+
require_relative 'smart_granular_scope_selection_test'
|
3
|
+
|
4
|
+
module ONCCertificationG10TestKit
|
5
|
+
class SmartGranularScopeSelectionGroup < Inferno::TestGroup
|
6
|
+
title 'SMART Granular Scope Selection'
|
7
|
+
short_title 'SMART Granular Scope Selection'
|
8
|
+
id :g10_smart_granular_scope_selection
|
9
|
+
|
10
|
+
input_instructions %(
|
11
|
+
If necessary, register Inferno as a standalone application using the following information:
|
12
|
+
|
13
|
+
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
14
|
+
|
15
|
+
Once the test is running, Inferno will perform a launch. The tester must grant
|
16
|
+
a sub-resource scope for each Conditoin and Observation, instead of granting
|
17
|
+
access to all Condition and Observation resources:
|
18
|
+
|
19
|
+
* “Condition” sub-resource scopes “Encounter Diagnosis”, “Problem List”,
|
20
|
+
and “Health Concern”
|
21
|
+
* “Observation” sub-resource scopes “Clinical Test”, “Laboratory”,
|
22
|
+
“Social History”, “SDOH”, “Survey”, and “Vital Signs”
|
23
|
+
|
24
|
+
Additionally, please grant access to the Patient scope.
|
25
|
+
|
26
|
+
)
|
27
|
+
|
28
|
+
description <<~DESCRIPTION
|
29
|
+
This scenario verifies that when resource-level scopes are requested for
|
30
|
+
Condition and Observation resources, the user is presented with the option
|
31
|
+
of granting sub-resource scopes instead of the requested resource-level scope if desired.
|
32
|
+
|
33
|
+
This scenario verifies that system behavior is consistent with the
|
34
|
+
following clarification provided in the §170.315(g)(10) Standardized API
|
35
|
+
for patient and population services [Certification Companion
|
36
|
+
Guide](https://www.healthit.gov/test-method/standardized-api-patient-and-population-services#ccg):
|
37
|
+
|
38
|
+
> As part of supporting the SMART App Launch “permission-v2” capability
|
39
|
+
for the purposes of certification, if an app requests authorization for
|
40
|
+
a resource level scope for the “Condition” or “Observation” resources,
|
41
|
+
then for patient authorization purposes a Health IT Module must support
|
42
|
+
presentation of the required sub-resource scopes to the patient for
|
43
|
+
authorization. Specifically, sub-resource scopes must be presented for
|
44
|
+
patient authorization as follows:
|
45
|
+
|
46
|
+
> * “Condition” sub-resource scopes “Encounter Diagnosis”, “Problem List”,
|
47
|
+
and “Health Concern” if a “Condition” resource level scope is
|
48
|
+
requested
|
49
|
+
> * “Observation” sub-resource scopes “Clinical Test”, “Laboratory”,
|
50
|
+
“Social History”, “SDOH”, “Survey”, and “Vital Signs” if an
|
51
|
+
“Observation” resource level scope is requested
|
52
|
+
|
53
|
+
The tests request SMART App Launch v2 resource-level Condition and
|
54
|
+
Observation scopes. In each instance, the user must not grant the
|
55
|
+
resource-level scopes and instead grant any valid sub-resource scope for
|
56
|
+
Condition and Observation listed above. This scenario also requires that a
|
57
|
+
resource-level Patient scope be granted.
|
58
|
+
|
59
|
+
This scenario only verifies that sub-resource scopes are granted as returned by the
|
60
|
+
authorization system during the SMART App Launch process, and does not
|
61
|
+
attempt to access resources to verify accuracy of the granted scopes.
|
62
|
+
|
63
|
+
DESCRIPTION
|
64
|
+
|
65
|
+
run_as_group
|
66
|
+
|
67
|
+
config(
|
68
|
+
inputs: {
|
69
|
+
use_pkce: {
|
70
|
+
default: 'true',
|
71
|
+
locked: true
|
72
|
+
},
|
73
|
+
pkce_code_challenge_method: {
|
74
|
+
locked: true
|
75
|
+
},
|
76
|
+
granular_scope_selection_authorization_method: {
|
77
|
+
name: :granular_scope_selection_authorization_method,
|
78
|
+
default: 'get'
|
79
|
+
},
|
80
|
+
client_auth_type: {
|
81
|
+
name: :granular_scope_selection_client_auth_type,
|
82
|
+
default: 'confidential_asymmetric'
|
83
|
+
}
|
84
|
+
}
|
85
|
+
)
|
86
|
+
|
87
|
+
group from: :smart_discovery_stu2
|
88
|
+
|
89
|
+
group from: :smart_standalone_launch_stu2 do
|
90
|
+
id :g10_granular_scope_selection_v2_scopes
|
91
|
+
title 'Granular Scope Selection with v2 Scopes'
|
92
|
+
|
93
|
+
config(
|
94
|
+
inputs: {
|
95
|
+
client_id: {
|
96
|
+
name: :granular_scope_selection_v2_client_id,
|
97
|
+
title: 'Granular Scope Selection w/v2 Scopes Client ID'
|
98
|
+
},
|
99
|
+
client_secret: {
|
100
|
+
name: :granular_scope_selection_v2_client_secret,
|
101
|
+
title: 'Granular Scope Selection w/v2 Scopes Client Secret',
|
102
|
+
default: nil,
|
103
|
+
optional: true
|
104
|
+
},
|
105
|
+
requested_scopes: {
|
106
|
+
name: :granular_scope_selection_v2_requested_scopes,
|
107
|
+
title: 'Granular Scope Selection v2 Scopes',
|
108
|
+
default: %(
|
109
|
+
launch/patient openid fhirUser offline_access patient/Condition.rs
|
110
|
+
patient/Observation.rs patient/Patient.rs
|
111
|
+
).gsub(/\s{2,}/, ' ').strip
|
112
|
+
},
|
113
|
+
received_scopes: { name: :granular_scope_selection_v2_received_scopes }
|
114
|
+
},
|
115
|
+
outputs: {
|
116
|
+
requested_scopes: { name: :granular_scope_selection_v2_requested_scopes },
|
117
|
+
received_scopes: { name: :granular_scope_selection_v2_received_scopes }
|
118
|
+
},
|
119
|
+
options: {
|
120
|
+
redirect_message_proc: proc do |auth_url|
|
121
|
+
%(
|
122
|
+
### #{self.class.parent&.parent&.title}
|
123
|
+
|
124
|
+
[Follow this link to authorize with the SMART server](#{auth_url}).
|
125
|
+
|
126
|
+
Tests will resume once Inferno receives a request at
|
127
|
+
`#{config.options[:redirect_uri]}` with a state of `#{state}`.
|
128
|
+
)
|
129
|
+
end
|
130
|
+
}
|
131
|
+
)
|
132
|
+
|
133
|
+
test from: :g10_smart_scopes do
|
134
|
+
config(
|
135
|
+
options: {
|
136
|
+
scope_version: :v2,
|
137
|
+
required_scope_type: 'patient',
|
138
|
+
required_scopes: ['openid', 'fhirUser', 'launch/patient', 'offline_access']
|
139
|
+
}
|
140
|
+
)
|
141
|
+
|
142
|
+
def patient_compartment_resource_types
|
143
|
+
['Patient', 'Condition', 'Observation']
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
test from: :g10_smart_granular_scope_selection
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ONCCertificationG10TestKit
|
2
|
+
class SMARTGranularScopeSelectionTest < Inferno::Test
|
3
|
+
title 'Granular Scope Selection'
|
4
|
+
description %(
|
5
|
+
This test verifies that granular scopes have been issued for Condition and
|
6
|
+
Observation resources, and that a v2 read scope has been issued for the
|
7
|
+
Patient resource.
|
8
|
+
)
|
9
|
+
id :g10_smart_granular_scope_selection
|
10
|
+
input :requested_scopes, :received_scopes
|
11
|
+
|
12
|
+
def resources_with_granular_scopes
|
13
|
+
['Condition', 'Observation']
|
14
|
+
end
|
15
|
+
|
16
|
+
def resource_level_scope_regex(resource_type)
|
17
|
+
/#{resource_type}\.(\*|read|c?ru?d?s?)\z/
|
18
|
+
end
|
19
|
+
|
20
|
+
def v2_resource_level_scope_regex(resource_type)
|
21
|
+
/#{resource_type}\.(\*|c?ru?d?s?)\z/
|
22
|
+
end
|
23
|
+
|
24
|
+
def granular_scope_regex(resource_type)
|
25
|
+
/#{resource_type}\.(\*|c?ru?d?s?)\?.+=.+/
|
26
|
+
end
|
27
|
+
|
28
|
+
run do
|
29
|
+
assert requested_scopes.present?
|
30
|
+
requested_scopes = self.requested_scopes.split
|
31
|
+
(resources_with_granular_scopes + ['Patient']).each do |resource_type|
|
32
|
+
assert requested_scopes.any? { |scope| scope.match(resource_level_scope_regex(resource_type)) },
|
33
|
+
"No resource-level scope was requested for #{resource_type}"
|
34
|
+
|
35
|
+
granular_scope = requested_scopes.find { |scope| scope.match(granular_scope_regex(resource_type)) }
|
36
|
+
assert granular_scope.nil?, "Granular scope was requested: #{granular_scope}"
|
37
|
+
end
|
38
|
+
|
39
|
+
assert received_scopes.present?
|
40
|
+
received_scopes = self.received_scopes.split
|
41
|
+
|
42
|
+
resources_with_granular_scopes.each do |resource_type|
|
43
|
+
resource_level_scope = received_scopes.find { |scope| scope.match?(resource_level_scope_regex(resource_type)) }
|
44
|
+
assert resource_level_scope.nil?, "Resource-level scope was granted: #{resource_level_scope}"
|
45
|
+
assert received_scopes.any? { |scope| scope.match?(granular_scope_regex(resource_type)) },
|
46
|
+
"No granular scopes were granted for #{resource_type}"
|
47
|
+
end
|
48
|
+
|
49
|
+
assert received_scopes.any? { |scope| scope.match?(v2_resource_level_scope_regex('Patient')) },
|
50
|
+
'No v2 resource-level scope was granted for Patient'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -41,21 +41,20 @@ module ONCCertificationG10TestKit
|
|
41
41
|
end
|
42
42
|
|
43
43
|
class SMARTInvalidPKCEGroup < Inferno::TestGroup
|
44
|
-
title '
|
45
|
-
short_title '
|
44
|
+
title 'Invalid PKCE Code Verifier'
|
45
|
+
short_title 'Invalid PKCE Code Verifier'
|
46
46
|
input_instructions %(
|
47
47
|
Register Inferno as a standalone application using the following information:
|
48
48
|
|
49
49
|
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
50
50
|
)
|
51
51
|
description %(
|
52
|
-
|
53
|
-
|
54
|
-
The #{title} Group verifies that a SMART Launch Sequence, specifically the
|
52
|
+
This scenario verifies that a SMART Launch Sequence, specifically the
|
55
53
|
[Standalone
|
56
54
|
Launch](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
57
|
-
Sequence, verifies that servers properly support PKCE. It does this by
|
58
|
-
in the case where the client sends an invalid
|
55
|
+
Sequence, verifies that servers properly support PKCE. It does this by
|
56
|
+
ensuring the launch fails in the case where the client sends an invalid
|
57
|
+
PKCE `code_verifier`.
|
59
58
|
|
60
59
|
This group performs four launches with various forms of an invalid `code_verifier`
|
61
60
|
(e.g. incorrect `code_verifier`, blank `code_identifier`) and verifies that these do
|
@@ -1,25 +1,23 @@
|
|
1
1
|
module ONCCertificationG10TestKit
|
2
2
|
class SMARTInvalidTokenGroup < Inferno::TestGroup
|
3
|
-
title '
|
4
|
-
short_title '
|
3
|
+
title 'Invalid Access Token Request'
|
4
|
+
short_title 'Invalid Token Request'
|
5
5
|
input_instructions %(
|
6
6
|
Register Inferno as a standalone application using the following information:
|
7
7
|
|
8
8
|
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
9
9
|
)
|
10
10
|
description %(
|
11
|
-
|
12
|
-
|
13
|
-
The Invalid Access Token Request Sequence verifies that a SMART Launch
|
11
|
+
This scenario verifies that a SMART Launch
|
14
12
|
Sequence, specifically the [Standalone
|
15
|
-
Launch](http://hl7.org/fhir/smart-app-launch/
|
16
|
-
Sequence, does not
|
13
|
+
Launch](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
14
|
+
Sequence, does not succeed in the case where the client sends an invalid
|
17
15
|
Authorization code or client ID during the code exchange step. This must
|
18
16
|
not result in a successful launch.
|
19
17
|
|
20
|
-
This test is not included as part of
|
21
|
-
|
22
|
-
|
18
|
+
This test is not included as part of earlier scenarios because some
|
19
|
+
servers may not accept an authorization code after it has been used
|
20
|
+
unsuccessfully in this manner.
|
23
21
|
)
|
24
22
|
id :g10_smart_invalid_token_request
|
25
23
|
run_as_group
|
@@ -1,25 +1,23 @@
|
|
1
1
|
module ONCCertificationG10TestKit
|
2
2
|
class SMARTInvalidTokenGroupSTU2 < Inferno::TestGroup
|
3
|
-
title '
|
4
|
-
short_title '
|
3
|
+
title 'Invalid Access Token Request'
|
4
|
+
short_title 'Invalid Token Request'
|
5
5
|
input_instructions %(
|
6
6
|
Register Inferno as a standalone application using the following information:
|
7
7
|
|
8
8
|
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
9
9
|
)
|
10
10
|
description %(
|
11
|
-
|
12
|
-
|
13
|
-
The Invalid Access Token Request Sequence verifies that a SMART Launch
|
11
|
+
This scenario verifies that a SMART Launch
|
14
12
|
Sequence, specifically the [Standalone
|
15
13
|
Launch](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
16
|
-
Sequence, does not
|
14
|
+
Sequence, does not succeed in the case where the client sends an invalid
|
17
15
|
Authorization code or client ID during the code exchange step. This must
|
18
16
|
not result in a successful launch.
|
19
17
|
|
20
|
-
This test is not included as part of
|
21
|
-
|
22
|
-
|
18
|
+
This test is not included as part of earlier scenarios because some
|
19
|
+
servers may not accept an authorization code after it has been used
|
20
|
+
unsuccessfully in this manner.
|
23
21
|
)
|
24
22
|
id :g10_smart_invalid_token_request_stu2
|
25
23
|
run_as_group
|
@@ -9,8 +9,8 @@ module ONCCertificationG10TestKit
|
|
9
9
|
short_title 'Limited Access App'
|
10
10
|
|
11
11
|
input_instructions %(
|
12
|
-
The purpose of this test is to
|
13
|
-
access granted to apps to a limited number of resources
|
12
|
+
The purpose of this test is to verify that patient app users can restrict
|
13
|
+
access granted to apps to a limited number of resources Enter which
|
14
14
|
resources the user will grant access to below, and during the launch
|
15
15
|
process only grant access to those resources. Inferno will verify that
|
16
16
|
access granted matches these expectations.
|
@@ -20,7 +20,7 @@ module ONCCertificationG10TestKit
|
|
20
20
|
)
|
21
21
|
|
22
22
|
description %(
|
23
|
-
This scenario
|
23
|
+
This scenario verifies the ability of a system to perform a Patient Standalone
|
24
24
|
Launch to a SMART on FHIR confidential client with limited access granted
|
25
25
|
to the app based on user input. The tester is expected to grant the
|
26
26
|
application access to a subset of desired resource types. The launch is
|
@@ -28,6 +28,8 @@ module ONCCertificationG10TestKit
|
|
28
28
|
App test, demonstrating that the user has control over what scopes are
|
29
29
|
granted to the app as required in the (g)(10) Standardized API criterion.
|
30
30
|
|
31
|
+
The following implementation specifications are relevant to this scenario:
|
32
|
+
|
31
33
|
* [SMART on FHIR
|
32
34
|
(STU1)](http://www.hl7.org/fhir/smart-app-launch/1.0.0/)
|
33
35
|
* [SMART on FHIR
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ONCCertificationG10TestKit
|
2
2
|
class SMARTPublicStandaloneLaunchGroup < SMARTAppLaunch::StandaloneLaunchGroup
|
3
|
-
title '
|
4
|
-
short_title '
|
3
|
+
title 'Public Client Standalone Launch with OpenID Connect'
|
4
|
+
short_title 'Public Client Launch'
|
5
5
|
input_instructions %(
|
6
6
|
Register Inferno as a standalone application using the following information:
|
7
7
|
|
@@ -13,23 +13,21 @@ module ONCCertificationG10TestKit
|
|
13
13
|
(offline_access), and patient context (launch/patient) are required.
|
14
14
|
)
|
15
15
|
description %(
|
16
|
-
# Background
|
17
16
|
|
18
|
-
|
19
|
-
Launch
|
20
|
-
|
21
|
-
|
22
|
-
the SMART App Launch Framework alongside EHR Launch. The app will
|
23
|
-
request authorization for the provided scope from the authorization
|
24
|
-
endpoint, ultimately receiving an authorization token which can be
|
25
|
-
used to gain access to resources on the FHIR server.
|
17
|
+
This scenario verifies the ability of systems to support public clients
|
18
|
+
as described in the SMART App Launch implementation specification. Previous
|
19
|
+
scenarios have not required the system under test to demonstrate this
|
20
|
+
specific type of SMART App Launch client.
|
26
21
|
|
27
|
-
|
22
|
+
Prior to executing this test, register Inferno as a public standalone
|
23
|
+
application using the following information:
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
authorization
|
25
|
+
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
26
|
+
|
27
|
+
Inferno will act as a public client redirect the tester to the the
|
28
|
+
authorization endpoint so that they may provide any required credentials
|
29
|
+
and authorize the application. Upon successful authorization, Inferno will
|
30
|
+
exchange the authorization code provided for an access token.
|
33
31
|
|
34
32
|
For more information on the #{title}:
|
35
33
|
|