onc_certification_g10_test_kit 2.3.0 → 3.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/inferno/terminology/expected_manifest.yml +242 -29
- data/lib/inferno/terminology/fhir_package_manager.rb +27 -0
- data/lib/inferno/terminology/loader.rb +22 -1
- data/lib/inferno/terminology/tasks/create_value_set_validators.rb +1 -1
- data/lib/inferno/terminology/tasks/download_fhir_terminology.rb +5 -0
- data/lib/inferno/terminology/value_set.rb +51 -5
- data/lib/onc_certification_g10_test_kit/base_token_refresh_group.rb +5 -4
- data/lib/onc_certification_g10_test_kit/bulk_data_group_export_stu1.rb +5 -0
- data/lib/onc_certification_g10_test_kit/bulk_data_group_export_stu2.rb +2 -0
- data/lib/onc_certification_g10_test_kit/bulk_data_group_export_validation.rb +206 -28
- data/lib/onc_certification_g10_test_kit/bulk_export_validation_tester.rb +25 -40
- data/lib/onc_certification_g10_test_kit/encounter_context_test.rb +30 -0
- data/lib/onc_certification_g10_test_kit/feature.rb +5 -8
- data/lib/onc_certification_g10_test_kit/limited_scope_grant_test.rb +18 -5
- data/lib/onc_certification_g10_test_kit/profile_selector.rb +175 -0
- data/lib/onc_certification_g10_test_kit/restricted_resource_type_access_group.rb +54 -4
- data/lib/onc_certification_g10_test_kit/single_patient_us_core_5_api_group.rb +93 -0
- data/lib/onc_certification_g10_test_kit/smart_app_launch_invalid_aud_group.rb +50 -5
- data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group.rb +94 -0
- data/lib/onc_certification_g10_test_kit/smart_ehr_patient_launch_group_stu2.rb +94 -0
- data/lib/onc_certification_g10_test_kit/smart_ehr_practitioner_app_group.rb +197 -13
- data/lib/onc_certification_g10_test_kit/smart_invalid_pkce_group.rb +310 -0
- data/lib/onc_certification_g10_test_kit/smart_invalid_token_group_stu2.rb +211 -0
- data/lib/onc_certification_g10_test_kit/smart_limited_app_group.rb +135 -9
- data/lib/onc_certification_g10_test_kit/smart_public_standalone_launch_group.rb +16 -4
- data/lib/onc_certification_g10_test_kit/smart_public_standalone_launch_group_stu2.rb +130 -0
- data/lib/onc_certification_g10_test_kit/smart_scopes_test.rb +134 -67
- data/lib/onc_certification_g10_test_kit/smart_standalone_patient_app_group.rb +166 -11
- data/lib/onc_certification_g10_test_kit/unrestricted_resource_type_access_group.rb +119 -135
- data/lib/onc_certification_g10_test_kit/version.rb +1 -1
- data/lib/onc_certification_g10_test_kit/visual_inspection_and_attestations_group.rb +19 -0
- data/lib/onc_certification_g10_test_kit/well_known_capabilities_test.rb +7 -1
- data/lib/onc_certification_g10_test_kit.rb +115 -74
- metadata +19 -11
- data/lib/onc_certification_g10_test_kit/profile_guesser.rb +0 -72
@@ -0,0 +1,211 @@
|
|
1
|
+
module ONCCertificationG10TestKit
|
2
|
+
class SMARTInvalidTokenGroupSTU2 < Inferno::TestGroup
|
3
|
+
title 'SMART App Launch Error: Invalid Access Token Request'
|
4
|
+
short_title 'SMART Invalid Token Request'
|
5
|
+
input_instructions %(
|
6
|
+
Register Inferno as a standalone application using the following information:
|
7
|
+
|
8
|
+
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
9
|
+
)
|
10
|
+
description %(
|
11
|
+
# Background
|
12
|
+
|
13
|
+
The Invalid Access Token Request Sequence verifies that a SMART Launch
|
14
|
+
Sequence, specifically the [Standalone
|
15
|
+
Launch](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
16
|
+
Sequence, does not work in the case where the client sends an invalid
|
17
|
+
Authorization code or client ID during the code exchange step. This must
|
18
|
+
not result in a successful launch.
|
19
|
+
|
20
|
+
This test is not included as part of a regular SMART Launch Sequence
|
21
|
+
because some servers may not accept an authorization code after it has
|
22
|
+
been used unsuccessfully in this manner.
|
23
|
+
)
|
24
|
+
id :g10_smart_invalid_token_request_stu2
|
25
|
+
run_as_group
|
26
|
+
|
27
|
+
input :use_pkce,
|
28
|
+
title: 'Proof Key for Code Exchange (PKCE)',
|
29
|
+
type: 'radio',
|
30
|
+
default: 'true',
|
31
|
+
locked: true,
|
32
|
+
options: {
|
33
|
+
list_options: [
|
34
|
+
{
|
35
|
+
label: 'Enabled',
|
36
|
+
value: 'true'
|
37
|
+
},
|
38
|
+
{
|
39
|
+
label: 'Disabled',
|
40
|
+
value: 'false'
|
41
|
+
}
|
42
|
+
]
|
43
|
+
}
|
44
|
+
input :pkce_code_challenge_method,
|
45
|
+
optional: true,
|
46
|
+
title: 'PKCE Code Challenge Method',
|
47
|
+
type: 'radio',
|
48
|
+
default: 'S256',
|
49
|
+
locked: true,
|
50
|
+
options: {
|
51
|
+
list_options: [
|
52
|
+
{
|
53
|
+
label: 'S256',
|
54
|
+
value: 'S256'
|
55
|
+
},
|
56
|
+
{
|
57
|
+
label: 'Plain',
|
58
|
+
value: 'plain'
|
59
|
+
}
|
60
|
+
]
|
61
|
+
}
|
62
|
+
|
63
|
+
input_order :url,
|
64
|
+
:standalone_client_id,
|
65
|
+
:standalone_client_secret,
|
66
|
+
:standalone_requested_scopes,
|
67
|
+
:use_pkce,
|
68
|
+
:pkce_code_challenge_method,
|
69
|
+
:smart_authorization_url,
|
70
|
+
:smart_token_url
|
71
|
+
|
72
|
+
config(
|
73
|
+
inputs: {
|
74
|
+
client_id: {
|
75
|
+
name: :standalone_client_id,
|
76
|
+
title: 'Standalone Client ID',
|
77
|
+
description: 'Client ID provided during registration of Inferno as a standalone application'
|
78
|
+
},
|
79
|
+
client_secret: {
|
80
|
+
name: :standalone_client_secret,
|
81
|
+
title: 'Standalone Client Secret',
|
82
|
+
description: 'Client Secret provided during registration of Inferno as a standalone application'
|
83
|
+
},
|
84
|
+
requested_scopes: {
|
85
|
+
name: :standalone_requested_scopes,
|
86
|
+
title: 'Standalone Scope',
|
87
|
+
description: 'OAuth 2.0 scope provided by system to enable all required functionality',
|
88
|
+
type: 'textarea',
|
89
|
+
default: %(
|
90
|
+
launch/patient openid fhirUser offline_access
|
91
|
+
patient/Medication.read patient/AllergyIntolerance.read
|
92
|
+
patient/CarePlan.read patient/CareTeam.read patient/Condition.read
|
93
|
+
patient/Device.read patient/DiagnosticReport.read
|
94
|
+
patient/DocumentReference.read patient/Encounter.read
|
95
|
+
patient/Goal.read patient/Immunization.read patient/Location.read
|
96
|
+
patient/MedicationRequest.read patient/Observation.read
|
97
|
+
patient/Organization.read patient/Patient.read
|
98
|
+
patient/Practitioner.read patient/Procedure.read
|
99
|
+
patient/Provenance.read patient/PractitionerRole.read
|
100
|
+
).gsub(/\s{2,}/, ' ').strip
|
101
|
+
},
|
102
|
+
url: {
|
103
|
+
title: 'Standalone FHIR Endpoint',
|
104
|
+
description: 'URL of the FHIR endpoint used by standalone applications'
|
105
|
+
},
|
106
|
+
code: {
|
107
|
+
name: :invalid_token_code
|
108
|
+
},
|
109
|
+
state: {
|
110
|
+
name: :invalid_token_state
|
111
|
+
},
|
112
|
+
smart_authorization_url: {
|
113
|
+
title: 'OAuth 2.0 Authorize Endpoint',
|
114
|
+
description: 'OAuth 2.0 Authorize Endpoint provided during the patient standalone launch'
|
115
|
+
},
|
116
|
+
smart_token_url: {
|
117
|
+
title: 'OAuth 2.0 Token Endpoint',
|
118
|
+
description: 'OAuth 2.0 Token Endpoint provided during the patient standalone launch'
|
119
|
+
},
|
120
|
+
pkce_code_verifier: {
|
121
|
+
name: :invalid_token_pkce_code_verifier
|
122
|
+
}
|
123
|
+
},
|
124
|
+
outputs: {
|
125
|
+
code: { name: :invalid_token_code },
|
126
|
+
state: { name: :invalid_token_state },
|
127
|
+
expires_in: { name: :invalid_token_expires_in },
|
128
|
+
pkce_code_verifier: { name: :invalid_token_pkce_code_verifier }
|
129
|
+
},
|
130
|
+
requests: {
|
131
|
+
redirect: { name: :invalid_token_redirect },
|
132
|
+
token: { name: :invalid_token_token }
|
133
|
+
}
|
134
|
+
)
|
135
|
+
|
136
|
+
test from: :smart_app_redirect_stu2
|
137
|
+
test from: :smart_code_received
|
138
|
+
|
139
|
+
test do
|
140
|
+
title ' OAuth token exchange fails when supplied invalid code'
|
141
|
+
description %(
|
142
|
+
If the request failed verification or is invalid, the authorization
|
143
|
+
server returns an error response.
|
144
|
+
)
|
145
|
+
uses_request :redirect
|
146
|
+
|
147
|
+
input :use_pkce, :pkce_code_verifier, :client_id, :client_secret, :smart_token_url
|
148
|
+
|
149
|
+
run do
|
150
|
+
skip_if request.query_parameters['error'].present?, 'Error during authorization request'
|
151
|
+
|
152
|
+
oauth2_params = {
|
153
|
+
grant_type: 'authorization_code',
|
154
|
+
code: 'BAD_CODE',
|
155
|
+
redirect_uri: config.options[:redirect_uri]
|
156
|
+
}
|
157
|
+
oauth2_headers = { 'Content-Type' => 'application/x-www-form-urlencoded' }
|
158
|
+
|
159
|
+
if client_secret.present?
|
160
|
+
client_credentials = "#{client_id}:#{client_secret}"
|
161
|
+
oauth2_headers['Authorization'] = "Basic #{Base64.strict_encode64(client_credentials)}"
|
162
|
+
else
|
163
|
+
oauth2_params[:client_id] = client_id
|
164
|
+
end
|
165
|
+
|
166
|
+
oauth2_params[:code_verifier] = pkce_code_verifier if use_pkce == 'true'
|
167
|
+
|
168
|
+
post(smart_token_url, body: oauth2_params, name: :token, headers: oauth2_headers)
|
169
|
+
|
170
|
+
assert_response_status(400)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
test do
|
175
|
+
title 'OAuth token exchange fails when supplied invalid client ID'
|
176
|
+
description %(
|
177
|
+
If the request failed verification or is invalid, the authorization
|
178
|
+
server returns an error response.
|
179
|
+
)
|
180
|
+
uses_request :redirect
|
181
|
+
|
182
|
+
input :use_pkce, :pkce_code_verifier, :code, :smart_token_url, :client_secret
|
183
|
+
|
184
|
+
run do
|
185
|
+
skip_if request.query_parameters['error'].present?, 'Error during authorization request'
|
186
|
+
|
187
|
+
client_id = 'BAD_CLIENT_ID'
|
188
|
+
|
189
|
+
oauth2_params = {
|
190
|
+
grant_type: 'authorization_code',
|
191
|
+
code: code,
|
192
|
+
redirect_uri: config.options[:redirect_uri]
|
193
|
+
}
|
194
|
+
oauth2_headers = { 'Content-Type' => 'application/x-www-form-urlencoded' }
|
195
|
+
|
196
|
+
if client_secret.present?
|
197
|
+
client_credentials = "#{client_id}:#{client_secret}"
|
198
|
+
oauth2_headers['Authorization'] = "Basic #{Base64.strict_encode64(client_credentials)}"
|
199
|
+
else
|
200
|
+
oauth2_params[:client_id] = client_id
|
201
|
+
end
|
202
|
+
|
203
|
+
oauth2_params[:code_verifier] = pkce_code_verifier if use_pkce == 'true'
|
204
|
+
|
205
|
+
post(smart_token_url, body: oauth2_params, name: :token, headers: oauth2_headers)
|
206
|
+
|
207
|
+
assert_response_status([400, 401])
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -20,13 +20,17 @@ module ONCCertificationG10TestKit
|
|
20
20
|
|
21
21
|
description %(
|
22
22
|
This scenario demonstrates the ability to perform a Patient Standalone
|
23
|
-
Launch to a
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
Launch to a SMART on FHIR confidential client with limited access granted
|
24
|
+
to the app based on user input. The tester is expected to grant the
|
25
|
+
application access to a subset of desired resource types. The launch is
|
26
|
+
performed using the same app configuration as in the Standalone Patient
|
27
|
+
App test, demonstrating that the user is control over what scopes are
|
28
|
+
granted to the app as required in the (g)(10) Standardized API criterion.
|
29
|
+
|
30
|
+
* [SMART on FHIR
|
31
|
+
(STU1)](http://www.hl7.org/fhir/smart-app-launch/1.0.0/)
|
32
|
+
* [SMART on FHIR
|
33
|
+
(STU2)](http://hl7.org/fhir/smart-app-launch/STU2)
|
30
34
|
)
|
31
35
|
id :g10_smart_limited_app
|
32
36
|
run_as_group
|
@@ -76,14 +80,14 @@ module ONCCertificationG10TestKit
|
|
76
80
|
Sequence](http://hl7.org/fhir/smart-app-launch/1.0.0/index.html#standalone-launch-sequence)
|
77
81
|
)
|
78
82
|
|
83
|
+
required_suite_options smart_app_launch_version: 'smart_app_launch_1'
|
84
|
+
|
79
85
|
config(
|
80
86
|
inputs: {
|
81
87
|
client_id: { locked: true },
|
82
88
|
client_secret: { locked: true, optional: false },
|
83
89
|
url: { locked: true },
|
84
90
|
requested_scopes: { locked: true },
|
85
|
-
use_pkce: { locked: true },
|
86
|
-
pkce_code_challenge_method: { locked: true },
|
87
91
|
code: { name: :limited_code },
|
88
92
|
state: { name: :limited_state },
|
89
93
|
patient_id: { name: :limited_patient_id },
|
@@ -161,6 +165,128 @@ module ONCCertificationG10TestKit
|
|
161
165
|
end
|
162
166
|
end
|
163
167
|
|
168
|
+
group from: :smart_standalone_launch_stu2,
|
169
|
+
config: {
|
170
|
+
inputs: {
|
171
|
+
use_pkce: {
|
172
|
+
default: 'true',
|
173
|
+
locked: true
|
174
|
+
},
|
175
|
+
pkce_code_challenge_method: {
|
176
|
+
locked: true
|
177
|
+
}
|
178
|
+
}
|
179
|
+
} do
|
180
|
+
title 'Standalone Launch With Limited Scope'
|
181
|
+
description %(
|
182
|
+
# Background
|
183
|
+
|
184
|
+
The [Standalone
|
185
|
+
Launch Sequence](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
186
|
+
allows an app, like Inferno, to be launched independent of an
|
187
|
+
existing EHR session. It is one of the two launch methods described in
|
188
|
+
the SMART App Launch Framework alongside EHR Launch. The app will
|
189
|
+
request authorization for the provided scope from the authorization
|
190
|
+
endpoint, ultimately receiving an authorization token which can be used
|
191
|
+
to gain access to resources on the FHIR server.
|
192
|
+
|
193
|
+
# Test Methodology
|
194
|
+
|
195
|
+
Inferno will redirect the user to the the authorization endpoint so that
|
196
|
+
they may provide any required credentials and authorize the application.
|
197
|
+
Upon successful authorization, Inferno will exchange the authorization
|
198
|
+
code provided for an access token.
|
199
|
+
|
200
|
+
For more information on the #{title}:
|
201
|
+
|
202
|
+
* [Standalone Launch
|
203
|
+
Sequence](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
204
|
+
)
|
205
|
+
|
206
|
+
required_suite_options smart_app_launch_version: 'smart_app_launch_2'
|
207
|
+
|
208
|
+
config(
|
209
|
+
inputs: {
|
210
|
+
client_id: { locked: true },
|
211
|
+
client_secret: { locked: true },
|
212
|
+
url: { locked: true },
|
213
|
+
requested_scopes: { locked: true },
|
214
|
+
code: { name: :limited_code },
|
215
|
+
state: { name: :limited_state },
|
216
|
+
patient_id: { name: :limited_patient_id },
|
217
|
+
access_token: { name: :limited_access_token },
|
218
|
+
# TODO: separate standalone/ehr discovery outputs
|
219
|
+
smart_authorization_url: { locked: true, title: 'SMART Authorization Url' },
|
220
|
+
smart_token_url: { locked: true, title: 'SMART Token Url' },
|
221
|
+
received_scopes: { name: :limited_received_scopes },
|
222
|
+
smart_credentials: { name: :limited_smart_credentials }
|
223
|
+
},
|
224
|
+
outputs: {
|
225
|
+
code: { name: :limited_code },
|
226
|
+
token_retrieval_time: { name: :limited_token_retrieval_time },
|
227
|
+
state: { name: :limited_state },
|
228
|
+
id_token: { name: :limited_id_token },
|
229
|
+
refresh_token: { name: :limited_refresh_token },
|
230
|
+
access_token: { name: :limited_access_token },
|
231
|
+
expires_in: { name: :limited_expires_in },
|
232
|
+
patient_id: { name: :limited_patient_id },
|
233
|
+
encounter_id: { name: :limited_encounter_id },
|
234
|
+
received_scopes: { name: :limited_received_scopes },
|
235
|
+
intent: { name: :limited_intent },
|
236
|
+
smart_credentials: { name: :limited_smart_credentials }
|
237
|
+
},
|
238
|
+
requests: {
|
239
|
+
redirect: { name: :limited_redirect },
|
240
|
+
token: { name: :limited_token }
|
241
|
+
},
|
242
|
+
options: {
|
243
|
+
redirect_message_proc: lambda do |auth_url|
|
244
|
+
expected_resource_string =
|
245
|
+
expected_resources
|
246
|
+
.split(',')
|
247
|
+
.map(&:strip)
|
248
|
+
.map { |resource_type| "* #{resource_type}\n" }
|
249
|
+
.join
|
250
|
+
|
251
|
+
<<~MESSAGE
|
252
|
+
### #{self.class.parent.parent.title}
|
253
|
+
|
254
|
+
[Follow this link to authorize with the SMART
|
255
|
+
server](#{auth_url}).
|
256
|
+
|
257
|
+
Tests will resume once Inferno receives a request at
|
258
|
+
`#{config.options[:redirect_uri]}` with a state of `#{state}`.
|
259
|
+
|
260
|
+
Access should only be granted to the following resources:
|
261
|
+
|
262
|
+
#{expected_resource_string}
|
263
|
+
MESSAGE
|
264
|
+
end
|
265
|
+
}
|
266
|
+
)
|
267
|
+
|
268
|
+
input :expected_resources,
|
269
|
+
title: 'Expected Resource Grant for Limited Access Launch',
|
270
|
+
description: 'The user will only grant access to the following resources during authorization.',
|
271
|
+
default: 'Patient, Condition, Observation'
|
272
|
+
|
273
|
+
test from: :g10_patient_context,
|
274
|
+
config: {
|
275
|
+
inputs: {
|
276
|
+
patient_id: { name: :limited_patient_id },
|
277
|
+
smart_credentials: { name: :limited_smart_credentials }
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
test from: :g10_limited_scope_grant do
|
282
|
+
config(
|
283
|
+
inputs: {
|
284
|
+
received_scopes: { name: :limited_received_scopes }
|
285
|
+
}
|
286
|
+
)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
164
290
|
group from: :g10_restricted_resource_type_access,
|
165
291
|
config: {
|
166
292
|
inputs: {
|
@@ -8,9 +8,9 @@ module ONCCertificationG10TestKit
|
|
8
8
|
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
9
9
|
|
10
10
|
Enter in the appropriate scope to enable patient-level access to all
|
11
|
-
relevant resources.
|
12
|
-
|
13
|
-
(launch/patient) are required.
|
11
|
+
relevant resources. If using SMART v2, v2-style scopes must be used. In
|
12
|
+
addition, support for the OpenID Connect (openid fhirUser), refresh tokens
|
13
|
+
(offline_access), and patient context (launch/patient) are required.
|
14
14
|
)
|
15
15
|
description %(
|
16
16
|
# Background
|
@@ -53,7 +53,19 @@ module ONCCertificationG10TestKit
|
|
53
53
|
},
|
54
54
|
requested_scopes: {
|
55
55
|
name: :public_requested_scopes,
|
56
|
-
title: 'Public Launch Scope'
|
56
|
+
title: 'Public Launch Scope',
|
57
|
+
default: %(
|
58
|
+
launch/patient openid fhirUser offline_access
|
59
|
+
patient/Medication.read patient/AllergyIntolerance.read
|
60
|
+
patient/CarePlan.read patient/CareTeam.read patient/Condition.read
|
61
|
+
patient/Device.read patient/DiagnosticReport.read
|
62
|
+
patient/DocumentReference.read patient/Encounter.read
|
63
|
+
patient/Goal.read patient/Immunization.read patient/Location.read
|
64
|
+
patient/MedicationRequest.read patient/Observation.read
|
65
|
+
patient/Organization.read patient/Patient.read
|
66
|
+
patient/Practitioner.read patient/Procedure.read
|
67
|
+
patient/Provenance.read patient/PractitionerRole.read
|
68
|
+
).gsub(/\s{2,}/, ' ').strip
|
57
69
|
},
|
58
70
|
url: {
|
59
71
|
title: 'Public Launch FHIR Endpoint',
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module ONCCertificationG10TestKit
|
2
|
+
class SMARTPublicStandaloneLaunchGroupSTU2 < SMARTAppLaunch::StandaloneLaunchGroupSTU2
|
3
|
+
title 'Public Client Standalone Launch with OpenID Connect'
|
4
|
+
short_title 'SMART Public Client Launch'
|
5
|
+
input_instructions %(
|
6
|
+
Register Inferno as a standalone application using the following information:
|
7
|
+
|
8
|
+
* Redirect URI: `#{SMARTAppLaunch::AppRedirectTest.config.options[:redirect_uri]}`
|
9
|
+
|
10
|
+
Enter in the appropriate scope to enable patient-level access to all
|
11
|
+
relevant resources. In addition, support for the OpenID Connect (openid
|
12
|
+
fhirUser), refresh tokens (offline_access), and patient context
|
13
|
+
(launch/patient) are required.
|
14
|
+
)
|
15
|
+
id :g10_public_standalone_launch_stu2
|
16
|
+
run_as_group
|
17
|
+
|
18
|
+
config(
|
19
|
+
inputs: {
|
20
|
+
client_id: {
|
21
|
+
name: :public_client_id,
|
22
|
+
title: 'Public Launch Client ID'
|
23
|
+
},
|
24
|
+
client_secret: {
|
25
|
+
name: :public_client_secret,
|
26
|
+
title: 'Public Launch Client Secret',
|
27
|
+
default: nil,
|
28
|
+
optional: true,
|
29
|
+
locked: true
|
30
|
+
},
|
31
|
+
requested_scopes: {
|
32
|
+
name: :public_requested_scopes,
|
33
|
+
title: 'Public Launch Scope',
|
34
|
+
default: %(
|
35
|
+
launch/patient openid fhirUser offline_access patient/Medication.rs
|
36
|
+
patient/AllergyIntolerance.rs patient/CarePlan.rs
|
37
|
+
patient/CareTeam.rs patient/Condition.rs patient/Device.rs
|
38
|
+
patient/DiagnosticReport.rs patient/DocumentReference.rs
|
39
|
+
patient/Encounter.rs patient/Goal.rs patient/Immunization.rs
|
40
|
+
patient/Location.rs patient/MedicationRequest.rs
|
41
|
+
patient/Observation.rs patient/Organization.rs patient/Patient.rs
|
42
|
+
patient/Practitioner.rs patient/Procedure.rs patient/Provenance.rs
|
43
|
+
patient/PractitionerRole.rs
|
44
|
+
).gsub(/\s{2,}/, ' ').strip
|
45
|
+
},
|
46
|
+
url: {
|
47
|
+
title: 'Public Launch FHIR Endpoint',
|
48
|
+
description: 'URL of the FHIR endpoint used by standalone applications'
|
49
|
+
},
|
50
|
+
code: {
|
51
|
+
name: :public_code
|
52
|
+
},
|
53
|
+
state: {
|
54
|
+
name: :public_state
|
55
|
+
},
|
56
|
+
smart_authorization_url: {
|
57
|
+
title: 'OAuth 2.0 Authorize Endpoint',
|
58
|
+
description: 'OAuth 2.0 Authorize Endpoint provided during the patient standalone launch'
|
59
|
+
},
|
60
|
+
smart_token_url: {
|
61
|
+
title: 'OAuth 2.0 Token Endpoint',
|
62
|
+
description: 'OAuth 2.0 Token Endpoint provided during the patient standalone launch'
|
63
|
+
},
|
64
|
+
smart_credentials: {
|
65
|
+
name: :public_smart_credentials
|
66
|
+
},
|
67
|
+
use_pkce: {
|
68
|
+
default: 'true',
|
69
|
+
locked: true
|
70
|
+
},
|
71
|
+
pkce_code_challenge_method: {
|
72
|
+
locked: true
|
73
|
+
}
|
74
|
+
},
|
75
|
+
outputs: {
|
76
|
+
code: { name: :public_code },
|
77
|
+
token_retrieval_time: { name: :public_token_retrieval_time },
|
78
|
+
state: { name: :public_state },
|
79
|
+
id_token: { name: :public_id_token },
|
80
|
+
refresh_token: { name: :public_refresh_token },
|
81
|
+
access_token: { name: :public_access_token },
|
82
|
+
expires_in: { name: :public_expires_in },
|
83
|
+
patient_id: { name: :public_patient_id },
|
84
|
+
encounter_id: { name: :public_encounter_id },
|
85
|
+
received_scopes: { name: :public_received_scopes },
|
86
|
+
intent: { name: :public_intent },
|
87
|
+
smart_credentials: { name: :public_smart_credentials }
|
88
|
+
},
|
89
|
+
requests: {
|
90
|
+
redirect: { name: :public_redirect },
|
91
|
+
token: { name: :public_token }
|
92
|
+
}
|
93
|
+
)
|
94
|
+
|
95
|
+
input_order :url,
|
96
|
+
:public_client_id,
|
97
|
+
:public_client_secret,
|
98
|
+
:public_requested_scopes,
|
99
|
+
:use_pkce,
|
100
|
+
:pkce_code_challenge_method,
|
101
|
+
:smart_authorization_url,
|
102
|
+
:smart_token_url
|
103
|
+
|
104
|
+
test from: :g10_patient_context,
|
105
|
+
config: {
|
106
|
+
inputs: {
|
107
|
+
patient_id: { name: :public_patient_id },
|
108
|
+
smart_credentials: { name: :public_smart_credentials }
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
test do
|
113
|
+
title 'OAuth token exchange response contains OpenID Connect id_token'
|
114
|
+
description %(
|
115
|
+
This test requires that an OpenID Connect id_token is provided to
|
116
|
+
demonstrate authentication capabilies for public clients.
|
117
|
+
)
|
118
|
+
id :g10_public_launch_id_token
|
119
|
+
|
120
|
+
input :id_token,
|
121
|
+
name: :public_id_token,
|
122
|
+
locked: true,
|
123
|
+
optional: true
|
124
|
+
|
125
|
+
run do
|
126
|
+
assert id_token.present?, 'Token response did not provide an id_token as required.'
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|