smart_app_launch_test_kit 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/smart_app_launch/app_launch_test.rb +14 -4
- data/lib/smart_app_launch/app_redirect_test.rb +9 -2
- data/lib/smart_app_launch/{discovery_group.rb → discovery_stu1_group.rb} +8 -78
- data/lib/smart_app_launch/discovery_stu2_group.rb +50 -0
- data/lib/smart_app_launch/ehr_launch_group_stu2.rb +45 -0
- data/lib/smart_app_launch/smart_stu1_suite.rb +154 -0
- data/lib/smart_app_launch/smart_stu2_suite.rb +154 -0
- data/lib/smart_app_launch/standalone_launch_group_stu2.rb +43 -0
- data/lib/smart_app_launch/token_refresh_test.rb +3 -3
- data/lib/smart_app_launch/version.rb +1 -1
- data/lib/smart_app_launch/well_known_capabilities_stu1_test.rb +39 -0
- data/lib/smart_app_launch/well_known_capabilities_stu2_test.rb +61 -0
- data/lib/smart_app_launch/well_known_endpoint_test.rb +46 -0
- data/lib/smart_app_launch_test_kit.rb +2 -172
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa36db12fcfc122798d91b90db284ba19912e36f0f9086a8fe193ddcead7417d
|
4
|
+
data.tar.gz: a78b8efce897f363156cfcad7bdcf49279b95da08dd26c4c4b2cc15f6ff424dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 590164ee28fbcd4d482656268af102328c534315cf55aa193ab55c8b4d4c806bef8735f5abd5ade375f89554849bcf3c6f60fa9206957ee64d6a6d5a491143c0
|
7
|
+
data.tar.gz: 0a779fd7a525a96edb4cc1f0dee37bfe5bc4ca1df772dd07fa92ca95c4f9722c35d81dd63ea4df1d2c038f0b344267be64f5700bf9e80a5f2aedc3514a9c33e9
|
@@ -12,13 +12,23 @@ module SMARTAppLaunch
|
|
12
12
|
|
13
13
|
config options: { launch_uri: "#{Inferno::Application['base_url']}/custom/smart/launch" }
|
14
14
|
|
15
|
+
def wait_message
|
16
|
+
return instance_exec(&config.options[:launch_message_proc]) if config.options[:launch_message_proc].present?
|
17
|
+
|
18
|
+
%(
|
19
|
+
### #{self.class.parent&.parent&.title}
|
20
|
+
|
21
|
+
Waiting for Inferno to be launched from the EHR.
|
22
|
+
|
23
|
+
Tests will resume once Inferno receives a launch request at
|
24
|
+
`#{config.options[:launch_uri]}` with an `iss` of `#{url}`.
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
15
28
|
run do
|
16
29
|
wait(
|
17
30
|
identifier: url,
|
18
|
-
message:
|
19
|
-
Waiting to receive a request at
|
20
|
-
`#{config.options[:launch_uri]}` with an `iss` of `#{url}`.
|
21
|
-
)
|
31
|
+
message: wait_message
|
22
32
|
)
|
23
33
|
end
|
24
34
|
end
|
@@ -58,10 +58,17 @@ module SMARTAppLaunch
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def wait_message(auth_url)
|
61
|
+
if config.options[:redirect_message_proc].present?
|
62
|
+
return instance_exec(auth_url, &config.options[:redirect_message_proc])
|
63
|
+
end
|
64
|
+
|
61
65
|
%(
|
66
|
+
### #{self.class.parent&.parent&.title}
|
67
|
+
|
62
68
|
[Follow this link to authorize with the SMART server](#{auth_url}).
|
63
|
-
|
64
|
-
a
|
69
|
+
|
70
|
+
Tests will resume once Inferno receives a request at
|
71
|
+
`#{config.options[:redirect_uri]}` with a state of `#{state}`.
|
65
72
|
)
|
66
73
|
end
|
67
74
|
|
@@ -1,5 +1,8 @@
|
|
1
|
+
require_relative 'well_known_capabilities_stu1_test'
|
2
|
+
require_relative 'well_known_endpoint_test'
|
3
|
+
|
1
4
|
module SMARTAppLaunch
|
2
|
-
class
|
5
|
+
class DiscoverySTU1Group < Inferno::TestGroup
|
3
6
|
id :smart_discovery
|
4
7
|
title 'SMART on FHIR Discovery'
|
5
8
|
short_description 'Retrieve server\'s SMART on FHIR configuration.'
|
@@ -36,83 +39,10 @@ module SMARTAppLaunch
|
|
36
39
|
* [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html)
|
37
40
|
)
|
38
41
|
|
39
|
-
test
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
be exposed as a Well-Known Uniform Resource Identifier
|
44
|
-
)
|
45
|
-
input :url,
|
46
|
-
title: 'FHIR Endpoint',
|
47
|
-
description: 'URL of the FHIR endpoint used by SMART applications'
|
48
|
-
output :well_known_configuration,
|
49
|
-
:well_known_authorization_url,
|
50
|
-
:well_known_introspection_url,
|
51
|
-
:well_known_management_url,
|
52
|
-
:well_known_registration_url,
|
53
|
-
:well_known_revocation_url,
|
54
|
-
:well_known_token_url
|
55
|
-
makes_request :smart_well_known_configuration
|
56
|
-
|
57
|
-
run do
|
58
|
-
well_known_configuration_url = "#{url.chomp('/')}/.well-known/smart-configuration"
|
59
|
-
get(well_known_configuration_url, name: :smart_well_known_configuration)
|
60
|
-
|
61
|
-
assert_response_status(200)
|
62
|
-
|
63
|
-
assert_valid_json(request.response_body)
|
64
|
-
|
65
|
-
config = JSON.parse(request.response_body)
|
66
|
-
output well_known_configuration: request.response_body,
|
67
|
-
well_known_authorization_url: config['authorization_endpoint'],
|
68
|
-
well_known_introspection_url: config['introspection_endpoint'],
|
69
|
-
well_known_management_url: config['management_endpoint'],
|
70
|
-
well_known_registration_url: config['registration_endpoint'],
|
71
|
-
well_known_revocation_url: config['revocation_endpoint'],
|
72
|
-
well_known_token_url: config['token_endpoint']
|
73
|
-
|
74
|
-
content_type = request.response_header('Content-Type')&.value
|
75
|
-
|
76
|
-
assert content_type.present?, 'No `Content-Type` header received.'
|
77
|
-
assert content_type.start_with?('application/json'),
|
78
|
-
"`Content-Type` must be `application/json`, but received: `#{content_type}`"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
test do
|
83
|
-
title 'Well-known configuration contains required fields'
|
84
|
-
description %(
|
85
|
-
The JSON from .well-known/smart-configuration contains the following
|
86
|
-
required fields: `authorization_endpoint`, `token_endpoint`,
|
87
|
-
`capabilities`
|
88
|
-
)
|
89
|
-
input :well_known_configuration
|
90
|
-
|
91
|
-
run do
|
92
|
-
skip_if well_known_configuration.blank?, 'No well-known configuration found'
|
93
|
-
config = JSON.parse(well_known_configuration)
|
94
|
-
|
95
|
-
['authorization_endpoint', 'token_endpoint', 'capabilities'].each do |key|
|
96
|
-
assert config.key?(key), "Well-known configuration does not include `#{key}`"
|
97
|
-
assert config[key].present?, "Well-known configuration field `#{key}` is blank"
|
98
|
-
end
|
99
|
-
|
100
|
-
assert config['authorization_endpoint'].is_a?(String),
|
101
|
-
'Well-known `authorization_endpoint` field must be a string'
|
102
|
-
assert config['token_endpoint'].is_a?(String),
|
103
|
-
'Well-known `token_endpoint` field must be a string'
|
104
|
-
assert config['capabilities'].is_a?(Array),
|
105
|
-
'Well-known `capabilities` field must be an array'
|
106
|
-
|
107
|
-
non_string_capabilities = config['capabilities'].reject { |capability| capability.is_a? String }
|
108
|
-
|
109
|
-
assert non_string_capabilities.blank?, %(
|
110
|
-
Well-known `capabilities` field must be an array of strings, but found
|
111
|
-
non-string values:
|
112
|
-
#{non_string_capabilities.map { |value| "`#{value.nil? ? 'nil' : value}`" }.join(', ')}
|
113
|
-
)
|
114
|
-
end
|
115
|
-
end
|
42
|
+
test from: :well_known_endpoint,
|
43
|
+
id: 'Test01'
|
44
|
+
test from: :well_known_capabilities_stu1,
|
45
|
+
id: 'Test02'
|
116
46
|
|
117
47
|
test do
|
118
48
|
title 'Conformance/CapabilityStatement provides OAuth 2.0 endpoints'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative 'well_known_capabilities_stu2_test'
|
2
|
+
require_relative 'well_known_endpoint_test'
|
3
|
+
|
4
|
+
module SMARTAppLaunch
|
5
|
+
class DiscoverySTU2Group < Inferno::TestGroup
|
6
|
+
id :smart_discovery_stu2
|
7
|
+
title 'SMART on FHIR Discovery'
|
8
|
+
short_description 'Retrieve server\'s SMART on FHIR configuration.'
|
9
|
+
description %(
|
10
|
+
# Background
|
11
|
+
|
12
|
+
The #{title} Sequence test looks for authorization endpoints and SMART
|
13
|
+
capabilities as described by the [SMART App Launch
|
14
|
+
Framework](http://hl7.org/fhir/smart-app-launch/STU2/).
|
15
|
+
The SMART launch framework uses OAuth 2.0 to *authorize* apps, like
|
16
|
+
Inferno, to access certain information on a FHIR server. The
|
17
|
+
authorization service accessed at the endpoint allows users to give
|
18
|
+
these apps permission without sharing their credentials with the
|
19
|
+
application itself. Instead, the application receives an access token
|
20
|
+
which allows it to access resources on the server. The access token
|
21
|
+
itself has a limited lifetime and permission scopes associated with it.
|
22
|
+
A refresh token may also be provided to the application in order to
|
23
|
+
obtain another access token. Unlike access tokens, a refresh token is
|
24
|
+
not shared with the resource server. If OpenID Connect is used, an id
|
25
|
+
token may be provided as well. The id token can be used to
|
26
|
+
*authenticate* the user. The id token is digitally signed and allows the
|
27
|
+
identity of the user to be verified.
|
28
|
+
|
29
|
+
# Test Methodology
|
30
|
+
|
31
|
+
This test suite will examine the SMART on FHIR configuration contained
|
32
|
+
in the `/.well-known/smart-configuration` endpoint.
|
33
|
+
|
34
|
+
For more information see:
|
35
|
+
|
36
|
+
* [SMART App Launch Framework](http://hl7.org/fhir/smart-app-launch/STU2/)
|
37
|
+
* [The OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749)
|
38
|
+
* [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html)
|
39
|
+
)
|
40
|
+
|
41
|
+
test from: :well_known_endpoint,
|
42
|
+
config: {
|
43
|
+
outputs: {
|
44
|
+
well_known_authorization_url: { name: :smart_authorization_url },
|
45
|
+
well_known_token_url: { name: :smart_token_url }
|
46
|
+
}
|
47
|
+
}
|
48
|
+
test from: :well_known_capabilities_stu2
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative 'ehr_launch_group'
|
2
|
+
|
3
|
+
module SMARTAppLaunch
|
4
|
+
class EHRLaunchGroupSTU2 < EHRLaunchGroup
|
5
|
+
id :smart_ehr_launch_stu2
|
6
|
+
description %(
|
7
|
+
# Background
|
8
|
+
|
9
|
+
The [EHR
|
10
|
+
Launch](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-ehr-launch)
|
11
|
+
is one of two ways in which an app can be launched, the other being
|
12
|
+
Standalone launch. In an EHR launch, the app is launched from an
|
13
|
+
existing EHR session or portal by a redirect to the registered launch
|
14
|
+
URL. The EHR provides the app two parameters:
|
15
|
+
|
16
|
+
* `iss` - Which contains the FHIR server url
|
17
|
+
* `launch` - An identifier needed for authorization
|
18
|
+
|
19
|
+
# Test Methodology
|
20
|
+
|
21
|
+
Inferno will wait for the EHR server redirect upon execution. When the
|
22
|
+
redirect is received Inferno will check for the presence of the `iss`
|
23
|
+
and `launch` parameters. The security of the authorization endpoint is
|
24
|
+
then checked and authorization is attempted using the provided `launch`
|
25
|
+
identifier.
|
26
|
+
|
27
|
+
For more information on the #{title} see:
|
28
|
+
|
29
|
+
* [SMART EHR Launch Sequence](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-ehr-launch)
|
30
|
+
)
|
31
|
+
|
32
|
+
config(
|
33
|
+
inputs: {
|
34
|
+
use_pkce: {
|
35
|
+
default: 'true',
|
36
|
+
locked: true
|
37
|
+
},
|
38
|
+
pkce_code_challenge_method: {
|
39
|
+
default: 'S256',
|
40
|
+
locked: true
|
41
|
+
}
|
42
|
+
}
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'tls_test_kit'
|
2
|
+
|
3
|
+
require_relative 'version'
|
4
|
+
require_relative 'discovery_stu1_group'
|
5
|
+
require_relative 'standalone_launch_group'
|
6
|
+
require_relative 'ehr_launch_group'
|
7
|
+
require_relative 'openid_connect_group'
|
8
|
+
require_relative 'token_refresh_group'
|
9
|
+
|
10
|
+
module SMARTAppLaunch
|
11
|
+
class SMARTSTU1Suite < Inferno::TestSuite
|
12
|
+
id 'smart'
|
13
|
+
title 'SMART App Launch STU1'
|
14
|
+
version VERSION
|
15
|
+
|
16
|
+
resume_test_route :get, '/launch' do
|
17
|
+
request.query_parameters['iss']
|
18
|
+
end
|
19
|
+
|
20
|
+
resume_test_route :get, '/redirect' do
|
21
|
+
request.query_parameters['state']
|
22
|
+
end
|
23
|
+
|
24
|
+
config options: {
|
25
|
+
redirect_uri: "#{Inferno::Application['base_url']}/custom/smart/redirect",
|
26
|
+
launch_uri: "#{Inferno::Application['base_url']}/custom/smart/launch"
|
27
|
+
}
|
28
|
+
|
29
|
+
group do
|
30
|
+
title 'Standalone Launch'
|
31
|
+
id :smart_full_standalone_launch
|
32
|
+
|
33
|
+
run_as_group
|
34
|
+
|
35
|
+
group from: :smart_discovery
|
36
|
+
group from: :smart_standalone_launch
|
37
|
+
|
38
|
+
group from: :smart_openid_connect,
|
39
|
+
config: {
|
40
|
+
inputs: {
|
41
|
+
id_token: { name: :standalone_id_token },
|
42
|
+
client_id: { name: :standalone_client_id },
|
43
|
+
requested_scopes: { name: :standalone_requested_scopes },
|
44
|
+
access_token: { name: :standalone_access_token },
|
45
|
+
smart_credentials: { name: :standalone_smart_credentials }
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
group from: :smart_token_refresh,
|
50
|
+
id: :smart_standalone_refresh_without_scopes,
|
51
|
+
title: 'SMART Token Refresh Without Scopes',
|
52
|
+
config: {
|
53
|
+
inputs: {
|
54
|
+
refresh_token: { name: :standalone_refresh_token },
|
55
|
+
client_id: { name: :standalone_client_id },
|
56
|
+
client_secret: { name: :standalone_client_secret },
|
57
|
+
received_scopes: { name: :standalone_received_scopes }
|
58
|
+
},
|
59
|
+
outputs: {
|
60
|
+
refresh_token: { name: :standalone_refresh_token },
|
61
|
+
received_scopes: { name: :standalone_received_scopes },
|
62
|
+
access_token: { name: :standalone_access_token },
|
63
|
+
token_retrieval_time: { name: :standalone_token_retrieval_time },
|
64
|
+
expires_in: { name: :standalone_expires_in },
|
65
|
+
smart_credentials: { name: :standalone_smart_credentials }
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
group from: :smart_token_refresh,
|
70
|
+
id: :smart_standalone_refresh_with_scopes,
|
71
|
+
title: 'SMART Token Refresh With Scopes',
|
72
|
+
config: {
|
73
|
+
options: { include_scopes: true },
|
74
|
+
inputs: {
|
75
|
+
refresh_token: { name: :standalone_refresh_token },
|
76
|
+
client_id: { name: :standalone_client_id },
|
77
|
+
client_secret: { name: :standalone_client_secret },
|
78
|
+
received_scopes: { name: :standalone_received_scopes }
|
79
|
+
},
|
80
|
+
outputs: {
|
81
|
+
refresh_token: { name: :standalone_refresh_token },
|
82
|
+
received_scopes: { name: :standalone_received_scopes },
|
83
|
+
access_token: { name: :standalone_access_token },
|
84
|
+
token_retrieval_time: { name: :standalone_token_retrieval_time },
|
85
|
+
expires_in: { name: :standalone_expires_in },
|
86
|
+
smart_credentials: { name: :standalone_smart_credentials }
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
group do
|
92
|
+
title 'EHR Launch'
|
93
|
+
id :smart_full_ehr_launch
|
94
|
+
|
95
|
+
run_as_group
|
96
|
+
|
97
|
+
group from: :smart_discovery
|
98
|
+
|
99
|
+
group from: :smart_ehr_launch
|
100
|
+
|
101
|
+
group from: :smart_openid_connect,
|
102
|
+
config: {
|
103
|
+
inputs: {
|
104
|
+
id_token: { name: :ehr_id_token },
|
105
|
+
client_id: { name: :ehr_client_id },
|
106
|
+
requested_scopes: { name: :ehr_requested_scopes },
|
107
|
+
access_token: { name: :ehr_access_token },
|
108
|
+
smart_credentials: { name: :ehr_smart_credentials }
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
group from: :smart_token_refresh,
|
113
|
+
id: :smart_ehr_refresh_without_scopes,
|
114
|
+
title: 'SMART Token Refresh Without Scopes',
|
115
|
+
config: {
|
116
|
+
inputs: {
|
117
|
+
refresh_token: { name: :ehr_refresh_token },
|
118
|
+
client_id: { name: :ehr_client_id },
|
119
|
+
client_secret: { name: :ehr_client_secret },
|
120
|
+
received_scopes: { name: :ehr_received_scopes }
|
121
|
+
},
|
122
|
+
outputs: {
|
123
|
+
refresh_token: { name: :ehr_refresh_token },
|
124
|
+
received_scopes: { name: :ehr_received_scopes },
|
125
|
+
access_token: { name: :ehr_access_token },
|
126
|
+
token_retrieval_time: { name: :ehr_token_retrieval_time },
|
127
|
+
expires_in: { name: :ehr_expires_in },
|
128
|
+
smart_credentials: { name: :ehr_smart_credentials }
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
group from: :smart_token_refresh,
|
133
|
+
id: :smart_ehr_refresh_with_scopes,
|
134
|
+
title: 'SMART Token Refresh With Scopes',
|
135
|
+
config: {
|
136
|
+
options: { include_scopes: true },
|
137
|
+
inputs: {
|
138
|
+
refresh_token: { name: :ehr_refresh_token },
|
139
|
+
client_id: { name: :ehr_client_id },
|
140
|
+
client_secret: { name: :ehr_client_secret },
|
141
|
+
received_scopes: { name: :ehr_received_scopes }
|
142
|
+
},
|
143
|
+
outputs: {
|
144
|
+
refresh_token: { name: :ehr_refresh_token },
|
145
|
+
received_scopes: { name: :ehr_received_scopes },
|
146
|
+
access_token: { name: :ehr_access_token },
|
147
|
+
token_retrieval_time: { name: :ehr_token_retrieval_time },
|
148
|
+
expires_in: { name: :ehr_expires_in },
|
149
|
+
smart_credentials: { name: :ehr_smart_credentials }
|
150
|
+
}
|
151
|
+
}
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'tls_test_kit'
|
2
|
+
|
3
|
+
require_relative 'version'
|
4
|
+
require_relative 'discovery_stu2_group'
|
5
|
+
require_relative 'standalone_launch_group_stu2'
|
6
|
+
require_relative 'ehr_launch_group_stu2'
|
7
|
+
require_relative 'openid_connect_group'
|
8
|
+
require_relative 'token_refresh_group'
|
9
|
+
|
10
|
+
module SMARTAppLaunch
|
11
|
+
class SMARTSTU2Suite < Inferno::TestSuite
|
12
|
+
id 'smart_stu2'
|
13
|
+
title 'SMART App Launch STU2 (Work in Progress)'
|
14
|
+
version VERSION
|
15
|
+
|
16
|
+
resume_test_route :get, '/launch' do
|
17
|
+
request.query_parameters['iss']
|
18
|
+
end
|
19
|
+
|
20
|
+
resume_test_route :get, '/redirect' do
|
21
|
+
request.query_parameters['state']
|
22
|
+
end
|
23
|
+
|
24
|
+
config options: {
|
25
|
+
redirect_uri: "#{Inferno::Application['base_url']}/custom/smart/redirect",
|
26
|
+
launch_uri: "#{Inferno::Application['base_url']}/custom/smart/launch"
|
27
|
+
}
|
28
|
+
|
29
|
+
group do
|
30
|
+
title 'Standalone Launch'
|
31
|
+
id :smart_full_standalone_launch
|
32
|
+
|
33
|
+
run_as_group
|
34
|
+
|
35
|
+
group from: :smart_discovery_stu2
|
36
|
+
group from: :smart_standalone_launch_stu2
|
37
|
+
|
38
|
+
group from: :smart_openid_connect,
|
39
|
+
config: {
|
40
|
+
inputs: {
|
41
|
+
id_token: { name: :standalone_id_token },
|
42
|
+
client_id: { name: :standalone_client_id },
|
43
|
+
requested_scopes: { name: :standalone_requested_scopes },
|
44
|
+
access_token: { name: :standalone_access_token },
|
45
|
+
smart_credentials: { name: :standalone_smart_credentials }
|
46
|
+
}
|
47
|
+
}
|
48
|
+
|
49
|
+
group from: :smart_token_refresh,
|
50
|
+
id: :smart_standalone_refresh_without_scopes,
|
51
|
+
title: 'SMART Token Refresh Without Scopes',
|
52
|
+
config: {
|
53
|
+
inputs: {
|
54
|
+
refresh_token: { name: :standalone_refresh_token },
|
55
|
+
client_id: { name: :standalone_client_id },
|
56
|
+
client_secret: { name: :standalone_client_secret },
|
57
|
+
received_scopes: { name: :standalone_received_scopes }
|
58
|
+
},
|
59
|
+
outputs: {
|
60
|
+
refresh_token: { name: :standalone_refresh_token },
|
61
|
+
received_scopes: { name: :standalone_received_scopes },
|
62
|
+
access_token: { name: :standalone_access_token },
|
63
|
+
token_retrieval_time: { name: :standalone_token_retrieval_time },
|
64
|
+
expires_in: { name: :standalone_expires_in },
|
65
|
+
smart_credentials: { name: :standalone_smart_credentials }
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
group from: :smart_token_refresh,
|
70
|
+
id: :smart_standalone_refresh_with_scopes,
|
71
|
+
title: 'SMART Token Refresh With Scopes',
|
72
|
+
config: {
|
73
|
+
options: { include_scopes: true },
|
74
|
+
inputs: {
|
75
|
+
refresh_token: { name: :standalone_refresh_token },
|
76
|
+
client_id: { name: :standalone_client_id },
|
77
|
+
client_secret: { name: :standalone_client_secret },
|
78
|
+
received_scopes: { name: :standalone_received_scopes }
|
79
|
+
},
|
80
|
+
outputs: {
|
81
|
+
refresh_token: { name: :standalone_refresh_token },
|
82
|
+
received_scopes: { name: :standalone_received_scopes },
|
83
|
+
access_token: { name: :standalone_access_token },
|
84
|
+
token_retrieval_time: { name: :standalone_token_retrieval_time },
|
85
|
+
expires_in: { name: :standalone_expires_in },
|
86
|
+
smart_credentials: { name: :standalone_smart_credentials }
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
group do
|
92
|
+
title 'EHR Launch'
|
93
|
+
id :smart_full_ehr_launch
|
94
|
+
|
95
|
+
run_as_group
|
96
|
+
|
97
|
+
group from: :smart_discovery_stu2
|
98
|
+
|
99
|
+
group from: :smart_ehr_launch_stu2
|
100
|
+
|
101
|
+
group from: :smart_openid_connect,
|
102
|
+
config: {
|
103
|
+
inputs: {
|
104
|
+
id_token: { name: :ehr_id_token },
|
105
|
+
client_id: { name: :ehr_client_id },
|
106
|
+
requested_scopes: { name: :ehr_requested_scopes },
|
107
|
+
access_token: { name: :ehr_access_token },
|
108
|
+
smart_credentials: { name: :ehr_smart_credentials }
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
group from: :smart_token_refresh,
|
113
|
+
id: :smart_ehr_refresh_without_scopes,
|
114
|
+
title: 'SMART Token Refresh Without Scopes',
|
115
|
+
config: {
|
116
|
+
inputs: {
|
117
|
+
refresh_token: { name: :ehr_refresh_token },
|
118
|
+
client_id: { name: :ehr_client_id },
|
119
|
+
client_secret: { name: :ehr_client_secret },
|
120
|
+
received_scopes: { name: :ehr_received_scopes }
|
121
|
+
},
|
122
|
+
outputs: {
|
123
|
+
refresh_token: { name: :ehr_refresh_token },
|
124
|
+
received_scopes: { name: :ehr_received_scopes },
|
125
|
+
access_token: { name: :ehr_access_token },
|
126
|
+
token_retrieval_time: { name: :ehr_token_retrieval_time },
|
127
|
+
expires_in: { name: :ehr_expires_in },
|
128
|
+
smart_credentials: { name: :ehr_smart_credentials }
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
group from: :smart_token_refresh,
|
133
|
+
id: :smart_ehr_refresh_with_scopes,
|
134
|
+
title: 'SMART Token Refresh With Scopes',
|
135
|
+
config: {
|
136
|
+
options: { include_scopes: true },
|
137
|
+
inputs: {
|
138
|
+
refresh_token: { name: :ehr_refresh_token },
|
139
|
+
client_id: { name: :ehr_client_id },
|
140
|
+
client_secret: { name: :ehr_client_secret },
|
141
|
+
received_scopes: { name: :ehr_received_scopes }
|
142
|
+
},
|
143
|
+
outputs: {
|
144
|
+
refresh_token: { name: :ehr_refresh_token },
|
145
|
+
received_scopes: { name: :ehr_received_scopes },
|
146
|
+
access_token: { name: :ehr_access_token },
|
147
|
+
token_retrieval_time: { name: :ehr_token_retrieval_time },
|
148
|
+
expires_in: { name: :ehr_expires_in },
|
149
|
+
smart_credentials: { name: :ehr_smart_credentials }
|
150
|
+
}
|
151
|
+
}
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative 'standalone_launch_group'
|
2
|
+
|
3
|
+
module SMARTAppLaunch
|
4
|
+
class StandaloneLaunchGroupSTU2 < StandaloneLaunchGroup
|
5
|
+
id :smart_standalone_launch_stu2
|
6
|
+
description %(
|
7
|
+
# Background
|
8
|
+
|
9
|
+
The [Standalone
|
10
|
+
Launch Sequence](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
11
|
+
allows an app, like Inferno, to be launched independent of an
|
12
|
+
existing EHR session. It is one of the two launch methods described in
|
13
|
+
the SMART App Launch Framework alongside EHR Launch. The app will
|
14
|
+
request authorization for the provided scope from the authorization
|
15
|
+
endpoint, ultimately receiving an authorization token which can be used
|
16
|
+
to gain access to resources on the FHIR server.
|
17
|
+
|
18
|
+
# Test Methodology
|
19
|
+
|
20
|
+
Inferno will redirect the user to the the authorization endpoint so that
|
21
|
+
they may provide any required credentials and authorize the application.
|
22
|
+
Upon successful authorization, Inferno will exchange the authorization
|
23
|
+
code provided for an access token.
|
24
|
+
|
25
|
+
For more information on the #{title}:
|
26
|
+
|
27
|
+
* [Standalone Launch Sequence](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#launch-app-standalone-launch)
|
28
|
+
)
|
29
|
+
|
30
|
+
config(
|
31
|
+
inputs: {
|
32
|
+
use_pkce: {
|
33
|
+
default: 'true',
|
34
|
+
locked: true
|
35
|
+
},
|
36
|
+
pkce_code_challenge_method: {
|
37
|
+
default: 'S256',
|
38
|
+
locked: true
|
39
|
+
}
|
40
|
+
}
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
@@ -16,7 +16,7 @@ module SMARTAppLaunch
|
|
16
16
|
the Pragma response header field with a value of no-cache to be
|
17
17
|
consistent with the requirements of the inital access token exchange.
|
18
18
|
)
|
19
|
-
input :
|
19
|
+
input :smart_token_url, :refresh_token, :client_id, :received_scopes
|
20
20
|
input :client_secret, optional: true
|
21
21
|
output :smart_credentials, :token_retrieval_time
|
22
22
|
makes_request :token_refresh
|
@@ -39,7 +39,7 @@ module SMARTAppLaunch
|
|
39
39
|
oauth2_params['client_id'] = client_id
|
40
40
|
end
|
41
41
|
|
42
|
-
post(
|
42
|
+
post(smart_token_url, body: oauth2_params, name: :token_refresh, headers: oauth2_headers)
|
43
43
|
|
44
44
|
assert_response_status(200)
|
45
45
|
assert_valid_json(request.response_body)
|
@@ -54,7 +54,7 @@ module SMARTAppLaunch
|
|
54
54
|
client_id: client_id,
|
55
55
|
client_secret: client_secret,
|
56
56
|
token_retrieval_time: token_retrieval_time,
|
57
|
-
token_url:
|
57
|
+
token_url: smart_token_url
|
58
58
|
}.to_json
|
59
59
|
end
|
60
60
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module SMARTAppLaunch
|
2
|
+
class WellKnownCapabilitiesSTU1Test < Inferno::Test
|
3
|
+
title 'Well-known configuration contains required fields'
|
4
|
+
id :well_known_capabilities_stu1
|
5
|
+
input :well_known_configuration
|
6
|
+
description %(
|
7
|
+
The JSON from .well-known/smart-configuration contains the following
|
8
|
+
required fields: `authorization_endpoint`, `token_endpoint`,
|
9
|
+
`capabilities`
|
10
|
+
)
|
11
|
+
|
12
|
+
def required_capabilities
|
13
|
+
{
|
14
|
+
'authorization_endpoint' => String,
|
15
|
+
'token_endpoint' => String,
|
16
|
+
'capabilities' => Array
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
run do
|
21
|
+
skip_if well_known_configuration.blank?, 'No well-known configuration found'
|
22
|
+
config = JSON.parse(well_known_configuration)
|
23
|
+
|
24
|
+
required_capabilities.each do |key, type|
|
25
|
+
assert config.key?(key), "Well-known configuration does not include `#{key}`"
|
26
|
+
assert config[key].present?, "Well-known configuration field `#{key}` is blank"
|
27
|
+
assert config[key].is_a?(type), "Well-known `#{key}` must be type: #{type.to_s.downcase}"
|
28
|
+
end
|
29
|
+
|
30
|
+
non_string_capabilities = config['capabilities'].reject { |capability| capability.is_a? String }
|
31
|
+
|
32
|
+
assert non_string_capabilities.blank?, %(
|
33
|
+
Well-known `capabilities` field must be an array of strings, but found
|
34
|
+
non-string values:
|
35
|
+
#{non_string_capabilities.map { |value| "`#{value.nil? ? 'nil' : value}`" }.join(', ')}
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module SMARTAppLaunch
|
2
|
+
class WellKnownCapabilitiesSTU2Test < Inferno::Test
|
3
|
+
title 'Well-known configuration contains required fields'
|
4
|
+
id :well_known_capabilities_stu2
|
5
|
+
input :well_known_configuration
|
6
|
+
description %(
|
7
|
+
The JSON from .well-known/smart-configuration contains the following
|
8
|
+
required fields: `authorization_endpoint`, `token_endpoint`,
|
9
|
+
`capabilities`, `grant_types_supported`, `code_challenge_methods_supported`.
|
10
|
+
If the `sso-openid-connect` capability is supported, then `issuer` and `jwks_uri` must be
|
11
|
+
present. If `sso-openid-connect` capability is not supported, then `issuer` must be omitted.
|
12
|
+
)
|
13
|
+
|
14
|
+
def required_capabilities
|
15
|
+
{
|
16
|
+
'authorization_endpoint' => String,
|
17
|
+
'token_endpoint' => String,
|
18
|
+
'capabilities' => Array,
|
19
|
+
'grant_types_supported' => Array,
|
20
|
+
'code_challenge_methods_supported' => Array
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
run do
|
25
|
+
skip_if well_known_configuration.blank?, 'No well-known configuration found'
|
26
|
+
config = JSON.parse(well_known_configuration)
|
27
|
+
|
28
|
+
required_capabilities.each do |key, type|
|
29
|
+
assert config.key?(key), "Well-known configuration does not include `#{key}`"
|
30
|
+
assert config[key].present?, "Well-known configuration field `#{key}` is blank"
|
31
|
+
assert config[key].is_a?(type), "Well-known `#{key}` must be type: #{type.to_s.downcase}"
|
32
|
+
end
|
33
|
+
|
34
|
+
assert config['grant_types_supported'].include?('authorization_code'),
|
35
|
+
'Well-known `grant_types_supported` must include `authorization_code` grant type to indicate SMART App Launch Support'
|
36
|
+
assert config['code_challenge_methods_supported'].include?('S256'),
|
37
|
+
'Well-known `code_challenge_methods_supported` must include `S256`'
|
38
|
+
assert config['code_challenge_methods_supported'].exclude?('plain'),
|
39
|
+
'Well-known `code_challenge_methods_support` must not include `plain`'
|
40
|
+
|
41
|
+
if config['capabilities'].include?('sso-openid-connect')
|
42
|
+
assert config['issuer'].is_a?(String),
|
43
|
+
'Well-known `issuer` field must be a string and present when server capabilities includes `sso-openid-connect`'
|
44
|
+
assert config['jwks_uri'].is_a?(String),
|
45
|
+
'Well-known `jwks_uri` field must be a string and present when server capabilites includes `sso-openid-coneect`'
|
46
|
+
else
|
47
|
+
warning do
|
48
|
+
assert config['issuer'].nil?, 'Well-known `issuer` is omitted when server capabilites does not include `sso-openid-connect`'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
non_string_capabilities = config['capabilities'].reject { |capability| capability.is_a? String }
|
53
|
+
|
54
|
+
assert non_string_capabilities.blank?, %(
|
55
|
+
Well-known `capabilities` field must be an array of strings, but found
|
56
|
+
non-string values:
|
57
|
+
#{non_string_capabilities.map { |value| "`#{value.nil? ? 'nil' : value}`" }.join(', ')}
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module SMARTAppLaunch
|
2
|
+
class WellKnownEndpointTest < Inferno::Test
|
3
|
+
title 'FHIR server makes SMART configuration available from well-known endpoint'
|
4
|
+
id :well_known_endpoint
|
5
|
+
description %(
|
6
|
+
The authorization endpoints accepted by a FHIR resource server can
|
7
|
+
be exposed as a Well-Known Uniform Resource Identifier
|
8
|
+
)
|
9
|
+
input :url,
|
10
|
+
title: 'FHIR Endpoint',
|
11
|
+
description: 'URL of the FHIR endpoint used by SMART applications'
|
12
|
+
output :well_known_configuration,
|
13
|
+
:well_known_authorization_url,
|
14
|
+
:well_known_introspection_url,
|
15
|
+
:well_known_management_url,
|
16
|
+
:well_known_registration_url,
|
17
|
+
:well_known_revocation_url,
|
18
|
+
:well_known_token_url
|
19
|
+
makes_request :smart_well_known_configuration
|
20
|
+
|
21
|
+
run do
|
22
|
+
well_known_configuration_url = "#{url.chomp('/')}/.well-known/smart-configuration"
|
23
|
+
get(well_known_configuration_url,
|
24
|
+
name: :smart_well_known_configuration,
|
25
|
+
headers: { 'Accept' => 'application/json' })
|
26
|
+
assert_response_status(200)
|
27
|
+
|
28
|
+
assert_valid_json(request.response_body)
|
29
|
+
|
30
|
+
config = JSON.parse(request.response_body)
|
31
|
+
output well_known_configuration: request.response_body,
|
32
|
+
well_known_authorization_url: config['authorization_endpoint'],
|
33
|
+
well_known_introspection_url: config['introspection_endpoint'],
|
34
|
+
well_known_management_url: config['management_endpoint'],
|
35
|
+
well_known_registration_url: config['registration_endpoint'],
|
36
|
+
well_known_revocation_url: config['revocation_endpoint'],
|
37
|
+
well_known_token_url: config['token_endpoint']
|
38
|
+
|
39
|
+
content_type = request.response_header('Content-Type')&.value
|
40
|
+
|
41
|
+
assert content_type.present?, 'No `Content-Type` header received.'
|
42
|
+
assert content_type.start_with?('application/json'),
|
43
|
+
"`Content-Type` must be `application/json`, but received: `#{content_type}`"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,174 +1,4 @@
|
|
1
1
|
require 'tls_test_kit'
|
2
2
|
|
3
|
-
require_relative 'smart_app_launch/
|
4
|
-
require_relative 'smart_app_launch/
|
5
|
-
require_relative 'smart_app_launch/standalone_launch_group'
|
6
|
-
require_relative 'smart_app_launch/ehr_launch_group'
|
7
|
-
require_relative 'smart_app_launch/openid_connect_group'
|
8
|
-
require_relative 'smart_app_launch/token_refresh_group'
|
9
|
-
|
10
|
-
# TODO: Remove once this functionality is released in core:
|
11
|
-
# https://github.com/inferno-framework/inferno-core/pull/86
|
12
|
-
module Inferno
|
13
|
-
module DSL
|
14
|
-
module Runnable
|
15
|
-
def required_inputs(prior_outputs = [])
|
16
|
-
required_inputs =
|
17
|
-
inputs
|
18
|
-
.reject { |input| input_definitions[input][:optional] }
|
19
|
-
.map { |input| config.input_name(input) }
|
20
|
-
.reject { |input| prior_outputs.include?(input) }
|
21
|
-
children_required_inputs = children.flat_map { |child| child.required_inputs(prior_outputs) }
|
22
|
-
prior_outputs.concat(outputs.map { |output| config.output_name(output) })
|
23
|
-
(required_inputs + children_required_inputs).flatten.uniq
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module SMARTAppLaunch
|
30
|
-
class SMARTSuite < Inferno::TestSuite
|
31
|
-
id 'smart'
|
32
|
-
title 'SMART App Launch STU1'
|
33
|
-
version VERSION
|
34
|
-
|
35
|
-
resume_test_route :get, '/launch' do
|
36
|
-
request.query_parameters['iss']
|
37
|
-
end
|
38
|
-
|
39
|
-
resume_test_route :get, '/redirect' do
|
40
|
-
request.query_parameters['state']
|
41
|
-
end
|
42
|
-
|
43
|
-
config options: {
|
44
|
-
redirect_uri: "#{Inferno::Application['base_url']}/custom/smart/redirect",
|
45
|
-
launch_uri: "#{Inferno::Application['base_url']}/custom/smart/launch"
|
46
|
-
}
|
47
|
-
|
48
|
-
group do
|
49
|
-
title 'Standalone Launch'
|
50
|
-
id :smart_full_standalone_launch
|
51
|
-
|
52
|
-
run_as_group
|
53
|
-
|
54
|
-
group from: :smart_discovery
|
55
|
-
|
56
|
-
group from: :smart_standalone_launch
|
57
|
-
|
58
|
-
group from: :smart_openid_connect,
|
59
|
-
config: {
|
60
|
-
inputs: {
|
61
|
-
id_token: { name: :standalone_id_token },
|
62
|
-
client_id: { name: :standalone_client_id },
|
63
|
-
requested_scopes: { name: :standalone_requested_scopes },
|
64
|
-
access_token: { name: :standalone_access_token },
|
65
|
-
smart_credentials: { name: :standalone_smart_credentials }
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
|
-
group from: :smart_token_refresh,
|
70
|
-
id: :smart_standalone_refresh_without_scopes,
|
71
|
-
title: 'SMART Token Refresh Without Scopes',
|
72
|
-
config: {
|
73
|
-
inputs: {
|
74
|
-
refresh_token: { name: :standalone_refresh_token },
|
75
|
-
client_id: { name: :standalone_client_id },
|
76
|
-
client_secret: { name: :standalone_client_secret },
|
77
|
-
received_scopes: { name: :standalone_received_scopes }
|
78
|
-
},
|
79
|
-
outputs: {
|
80
|
-
refresh_token: { name: :standalone_refresh_token },
|
81
|
-
received_scopes: { name: :standalone_received_scopes },
|
82
|
-
access_token: { name: :standalone_access_token },
|
83
|
-
token_retrieval_time: { name: :standalone_token_retrieval_time },
|
84
|
-
expires_in: { name: :standalone_expires_in },
|
85
|
-
smart_credentials: { name: :standalone_smart_credentials }
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
group from: :smart_token_refresh,
|
90
|
-
id: :smart_standalone_refresh_with_scopes,
|
91
|
-
title: 'SMART Token Refresh With Scopes',
|
92
|
-
config: {
|
93
|
-
options: { include_scopes: true },
|
94
|
-
inputs: {
|
95
|
-
refresh_token: { name: :standalone_refresh_token },
|
96
|
-
client_id: { name: :standalone_client_id },
|
97
|
-
client_secret: { name: :standalone_client_secret },
|
98
|
-
received_scopes: { name: :standalone_received_scopes }
|
99
|
-
},
|
100
|
-
outputs: {
|
101
|
-
refresh_token: { name: :standalone_refresh_token },
|
102
|
-
received_scopes: { name: :standalone_received_scopes },
|
103
|
-
access_token: { name: :standalone_access_token },
|
104
|
-
token_retrieval_time: { name: :standalone_token_retrieval_time },
|
105
|
-
expires_in: { name: :standalone_expires_in },
|
106
|
-
smart_credentials: { name: :standalone_smart_credentials }
|
107
|
-
}
|
108
|
-
}
|
109
|
-
end
|
110
|
-
|
111
|
-
group do
|
112
|
-
title 'EHR Launch'
|
113
|
-
id :smart_full_ehr_launch
|
114
|
-
|
115
|
-
run_as_group
|
116
|
-
|
117
|
-
group from: :smart_discovery
|
118
|
-
|
119
|
-
group from: :smart_ehr_launch
|
120
|
-
|
121
|
-
group from: :smart_openid_connect,
|
122
|
-
config: {
|
123
|
-
inputs: {
|
124
|
-
id_token: { name: :ehr_id_token },
|
125
|
-
client_id: { name: :ehr_client_id },
|
126
|
-
requested_scopes: { name: :ehr_requested_scopes },
|
127
|
-
access_token: { name: :ehr_access_token },
|
128
|
-
smart_credentials: { name: :ehr_smart_credentials }
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
group from: :smart_token_refresh,
|
133
|
-
id: :smart_ehr_refresh_without_scopes,
|
134
|
-
title: 'SMART Token Refresh Without Scopes',
|
135
|
-
config: {
|
136
|
-
inputs: {
|
137
|
-
refresh_token: { name: :ehr_refresh_token },
|
138
|
-
client_id: { name: :ehr_client_id },
|
139
|
-
client_secret: { name: :ehr_client_secret },
|
140
|
-
received_scopes: { name: :ehr_received_scopes }
|
141
|
-
},
|
142
|
-
outputs: {
|
143
|
-
refresh_token: { name: :ehr_refresh_token },
|
144
|
-
received_scopes: { name: :ehr_received_scopes },
|
145
|
-
access_token: { name: :ehr_access_token },
|
146
|
-
token_retrieval_time: { name: :ehr_token_retrieval_time },
|
147
|
-
expires_in: { name: :ehr_expires_in },
|
148
|
-
smart_credentials: { name: :ehr_smart_credentials }
|
149
|
-
}
|
150
|
-
}
|
151
|
-
|
152
|
-
group from: :smart_token_refresh,
|
153
|
-
id: :smart_ehr_refresh_with_scopes,
|
154
|
-
title: 'SMART Token Refresh With Scopes',
|
155
|
-
config: {
|
156
|
-
options: { include_scopes: true },
|
157
|
-
inputs: {
|
158
|
-
refresh_token: { name: :ehr_refresh_token },
|
159
|
-
client_id: { name: :ehr_client_id },
|
160
|
-
client_secret: { name: :ehr_client_secret },
|
161
|
-
received_scopes: { name: :ehr_received_scopes }
|
162
|
-
},
|
163
|
-
outputs: {
|
164
|
-
refresh_token: { name: :ehr_refresh_token },
|
165
|
-
received_scopes: { name: :ehr_received_scopes },
|
166
|
-
access_token: { name: :ehr_access_token },
|
167
|
-
token_retrieval_time: { name: :ehr_token_retrieval_time },
|
168
|
-
expires_in: { name: :ehr_expires_in },
|
169
|
-
smart_credentials: { name: :ehr_smart_credentials }
|
170
|
-
}
|
171
|
-
}
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
3
|
+
require_relative 'smart_app_launch/smart_stu1_suite'
|
4
|
+
require_relative 'smart_app_launch/smart_stu2_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.1.
|
4
|
+
version: 0.1.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: 2022-
|
11
|
+
date: 2022-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inferno_core
|
@@ -134,8 +134,10 @@ files:
|
|
134
134
|
- lib/smart_app_launch/app_launch_test.rb
|
135
135
|
- lib/smart_app_launch/app_redirect_test.rb
|
136
136
|
- lib/smart_app_launch/code_received_test.rb
|
137
|
-
- lib/smart_app_launch/
|
137
|
+
- lib/smart_app_launch/discovery_stu1_group.rb
|
138
|
+
- lib/smart_app_launch/discovery_stu2_group.rb
|
138
139
|
- lib/smart_app_launch/ehr_launch_group.rb
|
140
|
+
- lib/smart_app_launch/ehr_launch_group_stu2.rb
|
139
141
|
- lib/smart_app_launch/launch_received_test.rb
|
140
142
|
- lib/smart_app_launch/openid_connect_group.rb
|
141
143
|
- lib/smart_app_launch/openid_decode_id_token_test.rb
|
@@ -145,7 +147,10 @@ files:
|
|
145
147
|
- lib/smart_app_launch/openid_retrieve_jwks_test.rb
|
146
148
|
- lib/smart_app_launch/openid_token_header_test.rb
|
147
149
|
- lib/smart_app_launch/openid_token_payload_test.rb
|
150
|
+
- lib/smart_app_launch/smart_stu1_suite.rb
|
151
|
+
- lib/smart_app_launch/smart_stu2_suite.rb
|
148
152
|
- lib/smart_app_launch/standalone_launch_group.rb
|
153
|
+
- lib/smart_app_launch/standalone_launch_group_stu2.rb
|
149
154
|
- lib/smart_app_launch/token_exchange_test.rb
|
150
155
|
- lib/smart_app_launch/token_payload_validation.rb
|
151
156
|
- lib/smart_app_launch/token_refresh_body_test.rb
|
@@ -154,6 +159,9 @@ files:
|
|
154
159
|
- lib/smart_app_launch/token_response_body_test.rb
|
155
160
|
- lib/smart_app_launch/token_response_headers_test.rb
|
156
161
|
- lib/smart_app_launch/version.rb
|
162
|
+
- lib/smart_app_launch/well_known_capabilities_stu1_test.rb
|
163
|
+
- lib/smart_app_launch/well_known_capabilities_stu2_test.rb
|
164
|
+
- lib/smart_app_launch/well_known_endpoint_test.rb
|
157
165
|
- lib/smart_app_launch_test_kit.rb
|
158
166
|
homepage: https://github.com/inferno_framework/smart-app-launch-test-kit
|
159
167
|
licenses:
|