smart_app_launch_test_kit 0.4.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/inferno_reference_server_preset.json +103 -0
  3. data/config/presets/inferno_reference_server_stu2_2_preset.json +89 -0
  4. data/config/presets/inferno_reference_server_stu2_preset.json +89 -0
  5. data/config/presets/smart_access_brands.json.erb +13 -0
  6. data/config/presets/smart_access_brands_example_1.json +37 -0
  7. data/config/presets/smart_access_brands_example_2.json +37 -0
  8. data/config/presets/smart_access_brands_example_3.json +37 -0
  9. data/config/presets/smart_access_brands_example_4.json +37 -0
  10. data/lib/smart_app_launch/cors_metadata_request_test.rb +40 -0
  11. data/lib/smart_app_launch/cors_openid_fhir_user_claim_test.rb +48 -0
  12. data/lib/smart_app_launch/cors_token_exchange_test.rb +35 -0
  13. data/lib/smart_app_launch/cors_well_known_endpoint_test.rb +40 -0
  14. data/lib/smart_app_launch/discovery_stu2_2_group.rb +12 -0
  15. data/lib/smart_app_launch/ehr_launch_group_stu2_2.rb +14 -0
  16. data/lib/smart_app_launch/metadata.rb +75 -0
  17. data/lib/smart_app_launch/openid_connect_group_stu2_2.rb +40 -0
  18. data/lib/smart_app_launch/smart_access_brands_examples/smart_access_brands_example.json.erb +198 -0
  19. data/lib/smart_app_launch/smart_access_brands_suite.rb +4 -1
  20. data/lib/smart_app_launch/smart_stu1_suite.rb +7 -6
  21. data/lib/smart_app_launch/smart_stu2_2_suite.rb +10 -10
  22. data/lib/smart_app_launch/smart_stu2_suite.rb +11 -10
  23. data/lib/smart_app_launch/standalone_launch_group_stu2_2.rb +14 -0
  24. data/lib/smart_app_launch/token_exchange_stu2_2_test.rb +30 -0
  25. data/lib/smart_app_launch/token_exchange_test.rb +10 -14
  26. data/lib/smart_app_launch/token_introspection_access_token_group_stu2_2.rb +2 -4
  27. data/lib/smart_app_launch/token_introspection_group.rb +1 -2
  28. data/lib/smart_app_launch/token_introspection_group_stu2_2.rb +0 -21
  29. data/lib/smart_app_launch/token_introspection_request_group.rb +47 -36
  30. data/lib/smart_app_launch/token_refresh_test.rb +13 -9
  31. data/lib/smart_app_launch/version.rb +2 -1
  32. data/lib/smart_app_launch_test_kit.rb +1 -0
  33. metadata +26 -8
@@ -0,0 +1,75 @@
1
+ require_relative 'version'
2
+
3
+ module SMARTAppLaunch
4
+ class Metadata < Inferno::TestKit
5
+ id :smart_app_launch_test_kit
6
+ title 'SMART App Launch Test Kit'
7
+ description <<~DESCRIPTION
8
+ The SMART App Launch Test Kit primarily validates the conformance of an
9
+ authorization server implementation to a specified version of the [SMART
10
+ Application Launch Framework Implementation
11
+ Guide](http://hl7.org/fhir/smart-app-launch/index.html). This Test Kit also
12
+ provides Brand Bundle Publisher testing for the User-access Brands and Endpoints
13
+ specification. This Test Kit supports following versions of the SMART App
14
+ Launch IG: [STU1](https://hl7.org/fhir/smart-app-launch/1.0.0/),
15
+ [STU2](http://hl7.org/fhir/smart-app-launch/STU2/), and
16
+ [STU2.2](http://hl7.org/fhir/smart-app-launch/STU2.2/).
17
+ <!-- break -->
18
+
19
+ This Test Kit is [open
20
+ source](https://github.com/inferno-framework/smart-app-launch-test-kit#license)
21
+ and freely available for use or adoption by the health IT community including
22
+ EHR vendors, health app developers, and testing labs. It is built using the
23
+ [Inferno Framework](https://inferno-framework.github.io/inferno-core/). The
24
+ Inferno Framework is designed for reuse and aims to make it easier to build test
25
+ kits for any FHIR-based data exchange.
26
+
27
+ To run tests for a SMART App Launch authorization server, select one of the
28
+ "SMART App Launch" suites. To run tests for a Brand Bundle Publisher, select
29
+ the "SMART User-access Brands and Endpoints" suite.
30
+
31
+ ## Status
32
+
33
+ The SMART App Launch Test Kit primarily verifies that systems correctly
34
+ implement the SMART App Launch IG for providing authorization and/or
35
+ authentication services to client applications accessing HL7 FHIR APIs.
36
+
37
+ The test kit currently tests the following requirements:
38
+ - Standalone Launch
39
+ - EHR Launch
40
+
41
+ It also tests the ability of a Brand Bundle Publisher to publish a valid brand
42
+ bundle as described in the User-access Brands and Endpoints specification.
43
+
44
+ See the test descriptions within the test kit for detail on the specific
45
+ validations performed as part of testing these requirements.
46
+
47
+ ## Repository
48
+
49
+ The SMART App Launch Test Kit GitHub repository can be [found
50
+ here](https://github.com/inferno-framework/smart-app-launch-test-kit).
51
+
52
+ ## Providing Feedback and Reporting Issues
53
+
54
+ We welcome feedback on the tests, including but not limited to the following
55
+ areas:
56
+
57
+ - Validation logic, such as potential bugs, lax checks, and unexpected failures.
58
+ - Requirements coverage, such as requirements that have been missed, tests that
59
+ necessitate features that the IG does not require, or other issues with the
60
+ interpretation of the IG's requirements.
61
+ - User experience, such as confusing or missing information in the test UI.
62
+
63
+ Please report any issues with this set of tests in the [issues
64
+ section](https://github.com/inferno-framework/smart-app-launch-test-kit/issues)
65
+ of the repository.
66
+ DESCRIPTION
67
+ suite_ids [:smart, :smart_stu2, :smart_stu2_2, :smart_access_brands]
68
+ tags ['SMART App Launch', 'Endpoint Publication']
69
+ last_updated LAST_UPDATED
70
+ version VERSION
71
+ maturity 'Medium'
72
+ authors ['Stephen MacVicar']
73
+ repo 'https://github.com/inferno-framework/smart-app-launch-test-kit'
74
+ end
75
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'cors_openid_fhir_user_claim_test'
2
+ require_relative 'openid_connect_group'
3
+
4
+ module SMARTAppLaunch
5
+ class OpenIDConnectGroupSTU22 < OpenIDConnectGroup
6
+ id :smart_openid_connect_stu2_2
7
+ title 'OpenID Connect'
8
+ short_description 'Demonstrate the ability to authenticate users with OpenID Connect.'
9
+
10
+ description %(
11
+ # Background
12
+
13
+ OpenID Connect (OIDC) provides the ability to verify the identity of the
14
+ authorizing user. Within the [SMART App Launch
15
+ Framework](https://www.hl7.org/fhir/smart-app-launch/STU2.2/), Applications can
16
+ request an `id_token` be provided with by including the `openid fhirUser`
17
+ scopes when requesting authorization.
18
+
19
+ # Test Methodology
20
+
21
+ This sequence validates the id token returned as part of the OAuth 2.0
22
+ token response. Once the token is decoded, the server's OIDC configuration
23
+ is retrieved from its well-known configuration endpoint. This
24
+ configuration is checked to ensure that all required fields are present.
25
+ Next the keys used to cryptographically sign the id token are retrieved
26
+ from the url contained in the OIDC configuration. Then the header,
27
+ payload, and signature of the id token are validated. Finally, the FHIR
28
+ resource from the `fhirUser` claim in the id token is fetched from the
29
+ FHIR server.
30
+
31
+ For more information see:
32
+
33
+ * [SMART App Launch Framework](https://www.hl7.org/fhir/smart-app-launch/STU2.2/)
34
+ * [Scopes for requesting identity data](https://www.hl7.org/fhir/smart-app-launch/STU2.2/scopes-and-launch-context/index.html#scopes-for-requesting-identity-data)
35
+ * [Apps Requesting Authorization](https://www.hl7.org/fhir/smart-app-launch/STU2.2/index.html#step-1-app-asks-for-authorization)
36
+ * [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html)
37
+ )
38
+ test from: :smart_cors_openid_fhir_user_claim
39
+ end
40
+ end
@@ -0,0 +1,198 @@
1
+ {
2
+ "resourceType" : "Bundle",
3
+ "id" : "example3",
4
+ "type" : "collection",
5
+ "timestamp" : "2023-09-05T20:23:42.723178-07:00",
6
+ "entry" : [
7
+ {
8
+ "fullUrl" : "https://examplehospital.fhirserver.org/Organization/examplehospital",
9
+ "resource" : {
10
+ "resourceType" : "Organization",
11
+ "id" : "examplehospital",
12
+ "extension" : [
13
+ {
14
+ "extension" : [
15
+ {
16
+ "url" : "brandLogo",
17
+ "valueUrl" : "https://fhirserver.org/examplehospital-ehr1/themes/custom/logo.svg"
18
+ }
19
+ ],
20
+ "url" : "http://hl7.org/fhir/StructureDefinition/organization-brand"
21
+ },
22
+ {
23
+ "extension" : [
24
+ {
25
+ "url" : "portalName",
26
+ "valueString" : "ExampleHospital Patient Gateway"
27
+ },
28
+ {
29
+ "url" : "portalUrl",
30
+ "valueUrl" : "https://patientgateway.examplehospital.ehr1.fhirserver.org"
31
+ },
32
+ {
33
+ "url" : "portalDescription",
34
+ "valueMarkdown" : "Patient Gateway is an online tool to help adult patients connect with health care providers, manage appointments, and refill prescriptions.\n"
35
+ },
36
+ {
37
+ "url" : "portalEndpoint",
38
+ "valueReference" : {
39
+ "reference" : "https://ehr1.fhirserver.com/Endpoint/examplehospital-ehr1",
40
+ "display" : "FHIR R4 Endpoint for EHR1"
41
+ }
42
+ }
43
+ ],
44
+ "url" : "http://hl7.org/fhir/StructureDefinition/organization-portal"
45
+ },
46
+ {
47
+ "extension" : [
48
+ {
49
+ "url" : "portalName",
50
+ "valueString" : "ExampleHospital Pediatric Portal"
51
+ },
52
+ {
53
+ "url" : "portalUrl",
54
+ "valueUrl" : "https://pediatrics.examplehospital.ehr2.fhirserver.org"
55
+ },
56
+ {
57
+ "url" : "portalDescription",
58
+ "valueMarkdown" : "Pediatric Portal is the entrypoint for pediatric patients."
59
+ },
60
+ {
61
+ "url" : "portalEndpoint",
62
+ "valueReference" : {
63
+ "reference" : "https://ehr2.fhirserver.com/Endpoint/examplehospital-ehr2",
64
+ "display" : "FHIR R4 Endpoint for EHR2"
65
+ }
66
+ }
67
+ ],
68
+ "url" : "http://hl7.org/fhir/StructureDefinition/organization-portal"
69
+ }
70
+ ],
71
+ "identifier" : [
72
+ {
73
+ "system" : "urn:ietf:rfc:3986",
74
+ "value" : "https://examplehospital.fhirserver.org"
75
+ }
76
+ ],
77
+ "active" : true,
78
+ "type" : [
79
+ {
80
+ "coding" : [
81
+ {
82
+ "system" : "http://terminology.hl7.org/CodeSystem/organization-type",
83
+ "code" : "prov",
84
+ "display" : "Healthcare Provider"
85
+ }
86
+ ]
87
+ }
88
+ ],
89
+ "name" : "ExampleHospital",
90
+ "alias" : [
91
+ "GoodHealth Healthcare"
92
+ ],
93
+ "telecom" : [
94
+ {
95
+ "system" : "url",
96
+ "value" : "https://examplehospital.fhirserver.org/contact"
97
+ }
98
+ ],
99
+ "address" : [
100
+ {
101
+ "city" : "Boston",
102
+ "state" : "MA"
103
+ },
104
+ {
105
+ "city" : "Newton",
106
+ "state" : "MA"
107
+ },
108
+ {
109
+ "city" : "Waltham",
110
+ "state" : "MA"
111
+ }
112
+ ],
113
+ "endpoint" : [
114
+ {
115
+ "reference" : "https://ehr1.fhirserver.com/Endpoint/examplehospital-ehr1",
116
+ "display" : "FHIR R4 Endpoint for EHR1"
117
+ },
118
+ {
119
+ "reference" : "https://ehr2.fhirserver.com/Endpoint/examplehospital-ehr2",
120
+ "display" : "FHIR R4 Endpoint for EHR2"
121
+ }
122
+ ]
123
+ }
124
+ },
125
+ {
126
+ "fullUrl" : "https://ehr1.fhirserver.com/Endpoint/examplehospital-ehr1",
127
+ "resource" : {
128
+ "resourceType" : "Endpoint",
129
+ "id" : "examplehospital-ehr1",
130
+ "extension" : [
131
+ {
132
+ "url" : "http://hl7.org/fhir/StructureDefinition/endpoint-fhir-version",
133
+ "valueCode" : "4.0.1"
134
+ }
135
+ ],
136
+ "status" : "active",
137
+ "connectionType" : {
138
+ "system" : "http://terminology.hl7.org/CodeSystem/endpoint-connection-type",
139
+ "code" : "hl7-fhir-rest"
140
+ },
141
+ "name" : "FHIR R4 Endpoint for ExampleHospital's EHR1 Patient Gateway",
142
+ "contact" : [
143
+ {
144
+ "system" : "url",
145
+ "value" : "https://open.ehr1.fhirserver.com"
146
+ }
147
+ ],
148
+ "payloadType" : [
149
+ {
150
+ "coding" : [
151
+ {
152
+ "system" : "http://terminology.hl7.org/CodeSystem/endpoint-payload-type",
153
+ "code" : "none"
154
+ }
155
+ ]
156
+ }
157
+ ],
158
+ "address" : "<%= Inferno::Application['base_url'] %>/custom/smart_access_brands/examples/r4_capability_statement"
159
+ }
160
+ },
161
+ {
162
+ "fullUrl" : "https://ehr2.fhirserver.com/Endpoint/examplehospital-ehr2",
163
+ "resource" : {
164
+ "resourceType" : "Endpoint",
165
+ "id" : "examplehospital-ehr2",
166
+ "extension" : [
167
+ {
168
+ "url" : "http://hl7.org/fhir/StructureDefinition/endpoint-fhir-version",
169
+ "valueCode" : "4.0.1"
170
+ }
171
+ ],
172
+ "status" : "active",
173
+ "connectionType" : {
174
+ "system" : "http://terminology.hl7.org/CodeSystem/endpoint-connection-type",
175
+ "code" : "hl7-fhir-rest"
176
+ },
177
+ "name" : "FHIR R4 Endpoint for ExampleHospital's EHR2 Pediatric Portal",
178
+ "contact" : [
179
+ {
180
+ "system" : "url",
181
+ "value" : "https://open.ehr2.fhirserver.com"
182
+ }
183
+ ],
184
+ "payloadType" : [
185
+ {
186
+ "coding" : [
187
+ {
188
+ "system" : "http://terminology.hl7.org/CodeSystem/endpoint-payload-type",
189
+ "code" : "none"
190
+ }
191
+ ]
192
+ }
193
+ ],
194
+ "address" : "<%= Inferno::Application['base_url'] %>/custom/smart_access_brands/examples/r4_capability_statement"
195
+ }
196
+ }
197
+ ]
198
+ }
@@ -5,7 +5,6 @@ module SMARTAppLaunch
5
5
  id 'smart_access_brands'
6
6
  title 'SMART User-access Brands and Endpoints STU2.2'
7
7
  short_title 'SMART User-access Brands'
8
- version VERSION
9
8
 
10
9
  description <<~DESCRIPTION
11
10
  The SMART User-access Brands Test Suite verifies that Brand Bundle Publishers publish valid User-access
@@ -34,6 +33,10 @@ module SMARTAppLaunch
34
33
  Bundle as an input and leaving the User Access Brand Publication URL input blank.
35
34
  INSTRUCTIONS
36
35
 
36
+ source_code_url('https://github.com/inferno-framework/smart-app-launch-test-kit')
37
+ download_url('https://github.com/inferno-framework/smart-app-launch-test-kit/releases')
38
+ report_issue_url('https://github.com/inferno-framework/smart-app-launch-test-kit/issues')
39
+
37
40
  VALIDATION_MESSAGE_FILTERS = [
38
41
  /\A\S+: \S+: URL value '.*' does not resolve/,
39
42
  %r{\A\S+: \S+: Bundled or contained reference not found within the bundle/resource} # Validator issue with Brand profile: https://chat.fhir.org/#narrow/stream/291844-FHIR-Validator/topic/SMART.20v2.2E2.20User.20Access.20Brands.3A.20Brand.20validation.20error.3F/near/466321024
@@ -1,7 +1,6 @@
1
1
  require 'tls_test_kit'
2
2
 
3
3
  require_relative 'jwks'
4
- require_relative 'version'
5
4
  require_relative 'discovery_stu1_group'
6
5
  require_relative 'standalone_launch_group'
7
6
  require_relative 'ehr_launch_group'
@@ -12,7 +11,6 @@ module SMARTAppLaunch
12
11
  class SMARTSTU1Suite < Inferno::TestSuite
13
12
  id 'smart'
14
13
  title 'SMART App Launch STU1'
15
- version VERSION
16
14
 
17
15
  resume_test_route :get, '/launch' do |request|
18
16
  request.query_parameters['iss']
@@ -34,15 +32,18 @@ module SMARTAppLaunch
34
32
  }
35
33
 
36
34
  description <<~DESCRIPTION
37
- The SMART App Launch Test Suite verifies that systems correctly implement
38
- the [SMART App Launch IG](http://hl7.org/fhir/smart-app-launch/1.0.0/)
39
- for providing authorization and/or authentication services to client
40
- applications accessing HL7® FHIR® APIs. To get started, please first register
35
+ The SMART App Launch Test Suite verifies that systems correctly implement
36
+ the [SMART App Launch IG](http://hl7.org/fhir/smart-app-launch/1.0.0/)
37
+ for providing authorization and/or authentication services to client
38
+ applications accessing HL7® FHIR® APIs. To get started, please first register
41
39
  the Inferno client as a SMART App with the following information:
42
40
 
43
41
  * SMART Launch URI: `#{config.options[:launch_uri]}`
44
42
  * OAuth Redirect URI: `#{config.options[:redirect_uri]}`
45
43
  DESCRIPTION
44
+ source_code_url('https://github.com/inferno-framework/smart-app-launch-test-kit')
45
+ download_url('https://github.com/inferno-framework/smart-app-launch-test-kit/releases')
46
+ report_issue_url('https://github.com/inferno-framework/smart-app-launch-test-kit/issues')
46
47
 
47
48
  group do
48
49
  title 'Standalone Launch'
@@ -1,20 +1,17 @@
1
1
  require 'tls_test_kit'
2
2
 
3
3
  require_relative 'jwks'
4
- require_relative 'version'
5
- require_relative 'discovery_stu2_group'
4
+ require_relative 'discovery_stu2_2_group'
6
5
  require_relative 'standalone_launch_group_stu2_2'
7
6
  require_relative 'ehr_launch_group_stu2_2'
8
- require_relative 'openid_connect_group'
7
+ require_relative 'openid_connect_group_stu2_2'
9
8
  require_relative 'token_introspection_group_stu2_2'
10
- require_relative 'token_refresh_stu2_group'
11
9
  require_relative 'backend_services_authorization_group'
12
10
 
13
11
  module SMARTAppLaunch
14
12
  class SMARTSTU22Suite < Inferno::TestSuite
15
13
  id 'smart_stu2_2'
16
14
  title 'SMART App Launch STU2.2'
17
- version VERSION
18
15
 
19
16
  resume_test_route :get, '/launch' do |request|
20
17
  request.query_parameters['iss']
@@ -73,6 +70,9 @@ module SMARTAppLaunch
73
70
  If the token introspection endpoint of the system under test is NOT available at .well-known/smart-configuration,
74
71
  please run the test groups individually and group 3 Token Introspection will include the introspection endpoint as a manual input.
75
72
  )
73
+ source_code_url('https://github.com/inferno-framework/smart-app-launch-test-kit')
74
+ download_url('https://github.com/inferno-framework/smart-app-launch-test-kit/releases')
75
+ report_issue_url('https://github.com/inferno-framework/smart-app-launch-test-kit/issues')
76
76
 
77
77
  group do
78
78
  title 'Standalone Launch'
@@ -92,10 +92,10 @@ module SMARTAppLaunch
92
92
 
93
93
  run_as_group
94
94
 
95
- group from: :smart_discovery_stu2
95
+ group from: :smart_discovery_stu2_2
96
96
  group from: :smart_standalone_launch_stu2_2
97
97
 
98
- group from: :smart_openid_connect,
98
+ group from: :smart_openid_connect_stu2_2,
99
99
  config: {
100
100
  inputs: {
101
101
  id_token: { name: :standalone_id_token },
@@ -167,11 +167,11 @@ module SMARTAppLaunch
167
167
 
168
168
  run_as_group
169
169
 
170
- group from: :smart_discovery_stu2
170
+ group from: :smart_discovery_stu2_2
171
171
 
172
172
  group from: :smart_ehr_launch_stu2_2
173
173
 
174
- group from: :smart_openid_connect,
174
+ group from: :smart_openid_connect_stu2_2,
175
175
  config: {
176
176
  inputs: {
177
177
  id_token: { name: :ehr_id_token },
@@ -237,7 +237,7 @@ module SMARTAppLaunch
237
237
 
238
238
  run_as_group
239
239
 
240
- group from: :smart_discovery_stu2
240
+ group from: :smart_discovery_stu2_2
241
241
  group from: :backend_services_authorization
242
242
  end
243
243
 
@@ -1,7 +1,6 @@
1
1
  require 'tls_test_kit'
2
2
 
3
3
  require_relative 'jwks'
4
- require_relative 'version'
5
4
  require_relative 'discovery_stu2_group'
6
5
  require_relative 'standalone_launch_group_stu2'
7
6
  require_relative 'ehr_launch_group_stu2'
@@ -14,7 +13,6 @@ module SMARTAppLaunch
14
13
  class SMARTSTU2Suite < Inferno::TestSuite
15
14
  id 'smart_stu2'
16
15
  title 'SMART App Launch STU2'
17
- version VERSION
18
16
 
19
17
  resume_test_route :get, '/launch' do |request|
20
18
  request.query_parameters['iss']
@@ -42,10 +40,10 @@ module SMARTAppLaunch
42
40
  }
43
41
 
44
42
  description <<~DESCRIPTION
45
- The SMART App Launch Test Suite verifies that systems correctly implement
46
- the [SMART App Launch IG](http://hl7.org/fhir/smart-app-launch/STU2/)
47
- for providing authorization and/or authentication services to client
48
- applications accessing HL7® FHIR® APIs. To get started, please first register
43
+ The SMART App Launch Test Suite verifies that systems correctly implement
44
+ the [SMART App Launch IG](http://hl7.org/fhir/smart-app-launch/STU2/)
45
+ for providing authorization and/or authentication services to client
46
+ applications accessing HL7® FHIR® APIs. To get started, please first register
49
47
  the Inferno client as a SMART App with the following information:
50
48
 
51
49
  * SMART Launch URI: `#{config.options[:launch_uri]}`
@@ -59,17 +57,20 @@ module SMARTAppLaunch
59
57
 
60
58
  input_instructions %(
61
59
  When running tests at this level, the token introspection endpoint is not available as a manual input.
62
- Instead, group 3 Token Introspection will assume the token introspection endpoint
60
+ Instead, group 3 Token Introspection will assume the token introspection endpoint
63
61
  will be output from group 1 Standalone Launch tests, specifically the SMART On FHIR Discovery tests that query
64
62
  the .well-known/smart-configuration endpoint. However, including the token introspection
65
63
  endpoint as part of the well-known ouput is NOT required and is not formally checked in the SMART On FHIR Discovery
66
64
  tests. RFC-7662 on Token Introspection says that "The means by which the protected resource discovers the location of the introspection
67
65
  endpoint are outside the scope of this specification" and the Token Introspection IG does not add any further
68
- requirements to this.
66
+ requirements to this.
69
67
 
70
- If the token introspection endpoint of the system under test is NOT available at .well-known/smart-configuration,
71
- please run the test groups individually and group 3 Token Introspection will include the introspection endpoint as a manual input.
68
+ If the token introspection endpoint of the system under test is NOT available at .well-known/smart-configuration,
69
+ please run the test groups individually and group 3 Token Introspection will include the introspection endpoint as a manual input.
72
70
  )
71
+ source_code_url('https://github.com/inferno-framework/smart-app-launch-test-kit')
72
+ download_url('https://github.com/inferno-framework/smart-app-launch-test-kit/releases')
73
+ report_issue_url('https://github.com/inferno-framework/smart-app-launch-test-kit/issues')
73
74
 
74
75
  group do
75
76
  title 'Standalone Launch'
@@ -1,5 +1,7 @@
1
1
  require_relative 'token_response_body_test_stu2_2'
2
2
  require_relative 'standalone_launch_group_stu2'
3
+ require_relative 'cors_token_exchange_test'
4
+ require_relative 'token_exchange_stu2_2_test'
3
5
 
4
6
  module SMARTAppLaunch
5
7
  class StandaloneLaunchGroupSTU22 < StandaloneLaunchGroupSTU2
@@ -44,9 +46,21 @@ module SMARTAppLaunch
44
46
  }
45
47
  )
46
48
 
49
+ test from: :smart_token_exchange_stu2_2
50
+
51
+ token_exchange_index = children.find_index { |child| child.id.to_s.end_with? 'token_exchange' }
52
+ children[token_exchange_index] = children.pop
53
+
47
54
  test from: :smart_token_response_body_stu2_2
48
55
 
49
56
  token_response_body_index = children.find_index { |child| child.id.to_s.end_with? 'token_response_body' }
50
57
  children[token_response_body_index] = children.pop
58
+
59
+ test from: :smart_cors_token_exchange,
60
+ config: {
61
+ requests: {
62
+ cors_token_request: { name: :standalone_token }
63
+ }
64
+ }
51
65
  end
52
66
  end
@@ -0,0 +1,30 @@
1
+ require_relative 'token_exchange_stu2_test'
2
+
3
+ module SMARTAppLaunch
4
+ class TokenExchangeSTU22Test < TokenExchangeSTU2Test
5
+ id :smart_token_exchange_stu2_2
6
+
7
+ def add_credentials_to_request(oauth2_params, oauth2_headers)
8
+ if client_auth_type == 'confidential_symmetric'
9
+ assert client_secret.present?,
10
+ 'A client secret must be provided when using confidential symmetric client authentication.'
11
+
12
+ client_credentials = "#{client_id}:#{client_secret}"
13
+ oauth2_headers['Authorization'] = "Basic #{Base64.strict_encode64(client_credentials)}"
14
+ elsif client_auth_type == 'public'
15
+ oauth2_params[:client_id] = client_id
16
+ oauth2_headers['Origin'] = Inferno::Application['inferno_host']
17
+ else
18
+ oauth2_params.merge!(
19
+ client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
20
+ client_assertion: ClientAssertionBuilder.build(
21
+ iss: client_id,
22
+ sub: client_id,
23
+ aud: smart_token_url,
24
+ client_auth_encryption_method:
25
+ )
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
@@ -51,7 +51,7 @@ module SMARTAppLaunch
51
51
  skip_if request.query_parameters['error'].present?, 'Error during authorization request'
52
52
 
53
53
  oauth2_params = {
54
- code: code,
54
+ code:,
55
55
  redirect_uri: config.options[:redirect_uri],
56
56
  grant_type: 'authorization_code'
57
57
  }
@@ -59,9 +59,7 @@ module SMARTAppLaunch
59
59
 
60
60
  add_credentials_to_request(oauth2_params, oauth2_headers)
61
61
 
62
- if use_pkce == 'true'
63
- oauth2_params[:code_verifier] = pkce_code_verifier
64
- end
62
+ oauth2_params[:code_verifier] = pkce_code_verifier if use_pkce == 'true'
65
63
 
66
64
  post(smart_token_url, body: oauth2_params, name: :token, headers: oauth2_headers)
67
65
 
@@ -72,17 +70,15 @@ module SMARTAppLaunch
72
70
 
73
71
  token_response_body = JSON.parse(request.response_body)
74
72
 
75
-
76
73
  output smart_credentials: {
77
- refresh_token: token_response_body['refresh_token'],
78
- access_token: token_response_body['access_token'],
79
- expires_in: token_response_body['expires_in'],
80
- client_id: client_id,
81
- client_secret: client_secret,
82
- token_retrieval_time: token_retrieval_time,
83
- token_url: smart_token_url
84
- }.to_json
85
-
74
+ refresh_token: token_response_body['refresh_token'],
75
+ access_token: token_response_body['access_token'],
76
+ expires_in: token_response_body['expires_in'],
77
+ client_id:,
78
+ client_secret:,
79
+ token_retrieval_time:,
80
+ token_url: smart_token_url
81
+ }.to_json
86
82
  end
87
83
  end
88
84
  end
@@ -1,7 +1,7 @@
1
1
  require_relative 'standalone_launch_group_stu2_2'
2
2
 
3
3
  module SMARTAppLaunch
4
- class SMARTTokenIntrospectionAccessTokenGroupSTU22 < SMARTTokenIntrospectionAccessTokenGroup
4
+ class SMARTTokenIntrospectionAccessTokenGroupSTU22 < Inferno::TestGroup
5
5
  title 'Request New Access Token to Introspect'
6
6
  run_as_group
7
7
 
@@ -20,9 +20,7 @@ module SMARTAppLaunch
20
20
  Register Inferno as a Standalone SMART App and provide the registration details below.
21
21
  )
22
22
 
23
+ group from: :smart_discovery_stu2_2
23
24
  group from: :smart_standalone_launch_stu2_2
24
-
25
- standalone_launch_index = children.find_index { |child| child.id.to_s.end_with? 'standalone_launch_stu2' }
26
- children[standalone_launch_index] = children.pop
27
25
  end
28
26
  end
@@ -57,13 +57,12 @@ module SMARTAppLaunch
57
57
 
58
58
  If the introspection endpoint is protected, testers must enter their own HTTP Authorization header for the introspection request. See
59
59
  [RFC 7616 The 'Basic' HTTP Authentication Scheme](https://datatracker.ietf.org/doc/html/rfc7617) for the most common
60
- approach that uses client credentials. Testers may also provide any additional parameters needed for their authorization
60
+ approach that uses client credentials. Testers may also provide any additional parameters needed for their authorization
61
61
  server to complete the introspection request.
62
62
 
63
63
  **Note:** For both the Authorization header and request parameters, user-input
64
64
  values will be sent exactly as entered and therefore the tester must
65
65
  URI-encode any appropriate values.
66
66
  )
67
-
68
67
  end
69
68
  end
@@ -43,26 +43,5 @@ module SMARTAppLaunch
43
43
 
44
44
  access_token_group_index = children.find_index { |child| child.id.to_s.end_with? 'access_token_group' }
45
45
  children[access_token_group_index] = children.pop
46
-
47
- input_order :url, :standalone_client_id, :standalone_client_secret,
48
- :authorization_method, :use_pkce, :pkce_code_challenge_method,
49
- :standalone_requested_scopes, :client_auth_encryption_method,
50
- :client_auth_type, :custom_authorization_header,
51
- :optional_introspection_request_params
52
- input_instructions %(
53
- Executing tests at this level will run all three Token Introspection groups back-to-back. If test groups need
54
- to be run independently, exit this window and select a specific test group instead.
55
-
56
- These tests are currently designed such that the token introspection URL must be present in the SMART well-known endpoint.
57
-
58
- If the introspection endpoint is protected, testers must enter their own HTTP Authorization header for the introspection request. See
59
- [RFC 7616 The 'Basic' HTTP Authentication Scheme](https://datatracker.ietf.org/doc/html/rfc7617) for the most common
60
- approach that uses client credentials. Testers may also provide any additional parameters needed for their authorization
61
- server to complete the introspection request.
62
-
63
- **Note:** For both the Authorization header and request parameters, user-input
64
- values will be sent exactly as entered and therefore the tester must
65
- URI-encode any appropriate values.
66
- )
67
46
  end
68
47
  end