smart_app_launch_test_kit 0.5.1 → 0.6.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/inferno_reference_server_preset.json +15 -86
  3. data/config/presets/inferno_reference_server_stu2_2_preset.json +20 -69
  4. data/config/presets/inferno_reference_server_stu2_preset.json +20 -69
  5. data/lib/smart_app_launch/app_redirect_test.rb +12 -44
  6. data/lib/smart_app_launch/app_redirect_test_stu2.rb +2 -17
  7. data/lib/smart_app_launch/backend_services_authorization_group.rb +33 -57
  8. data/lib/smart_app_launch/backend_services_authorization_request_builder.rb +22 -9
  9. data/lib/smart_app_launch/backend_services_authorization_request_success_test.rb +26 -21
  10. data/lib/smart_app_launch/backend_services_authorization_response_body_test.rb +19 -5
  11. data/lib/smart_app_launch/backend_services_invalid_client_assertion_test.rb +30 -25
  12. data/lib/smart_app_launch/backend_services_invalid_grant_type_test.rb +30 -24
  13. data/lib/smart_app_launch/backend_services_invalid_jwt_test.rb +31 -26
  14. data/lib/smart_app_launch/client_assertion_builder.rb +27 -12
  15. data/lib/smart_app_launch/cors_openid_fhir_user_claim_test.rb +2 -2
  16. data/lib/smart_app_launch/cors_token_exchange_test.rb +2 -2
  17. data/lib/smart_app_launch/discovery_stu1_group.rb +6 -2
  18. data/lib/smart_app_launch/ehr_launch_group.rb +41 -24
  19. data/lib/smart_app_launch/ehr_launch_group_stu2.rb +26 -10
  20. data/lib/smart_app_launch/ehr_launch_group_stu2_2.rb +0 -16
  21. data/lib/smart_app_launch/openid_fhir_user_claim_test.rb +5 -4
  22. data/lib/smart_app_launch/openid_token_payload_test.rb +6 -8
  23. data/lib/smart_app_launch/smart_stu1_suite.rb +32 -24
  24. data/lib/smart_app_launch/smart_stu2_2_suite.rb +56 -30
  25. data/lib/smart_app_launch/smart_stu2_suite.rb +56 -31
  26. data/lib/smart_app_launch/smart_tls_test.rb +14 -0
  27. data/lib/smart_app_launch/standalone_launch_group.rb +42 -25
  28. data/lib/smart_app_launch/standalone_launch_group_stu2.rb +26 -10
  29. data/lib/smart_app_launch/standalone_launch_group_stu2_2.rb +0 -16
  30. data/lib/smart_app_launch/token_exchange_stu2_2_test.rb +5 -17
  31. data/lib/smart_app_launch/token_exchange_stu2_test.rb +8 -67
  32. data/lib/smart_app_launch/token_exchange_test.rb +18 -38
  33. data/lib/smart_app_launch/token_introspection_access_token_group.rb +12 -4
  34. data/lib/smart_app_launch/token_introspection_access_token_group_stu2_2.rb +9 -1
  35. data/lib/smart_app_launch/token_introspection_group.rb +2 -4
  36. data/lib/smart_app_launch/token_introspection_request_group.rb +2 -4
  37. data/lib/smart_app_launch/token_introspection_response_group.rb +64 -49
  38. data/lib/smart_app_launch/token_refresh_body_test.rb +9 -2
  39. data/lib/smart_app_launch/token_refresh_stu2_test.rb +10 -17
  40. data/lib/smart_app_launch/token_refresh_test.rb +19 -20
  41. data/lib/smart_app_launch/token_response_body_test.rb +14 -4
  42. data/lib/smart_app_launch/token_response_body_test_stu2_2.rb +3 -2
  43. data/lib/smart_app_launch/version.rb +2 -2
  44. data/lib/smart_app_launch/well_known_endpoint_test.rb +11 -1
  45. metadata +5 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f80a6156d7f541a28a876f54e29a1d7457b84c06feb6aea21d54a499e734ef91
4
- data.tar.gz: 9f0990127c9bd562c1328e82a53d0c431c08fb3fbb1fbd24735049a40303eaba
3
+ metadata.gz: fbce79e8d195045070c2257dc897fa511b981071d366875bf3aa36ccb338dbdd
4
+ data.tar.gz: 5ea51bb46c93c23186fa620908287f69bab62d42c8f5ecbf0ff70d39ec8523e0
5
5
  SHA512:
6
- metadata.gz: 819be8732a3feed22713a508e3f316101c5cfab62055b68666c94991359c79bc41159086c721b62886c3e38db51305e085ef4ef0dcaed7a9ab615600542a417c
7
- data.tar.gz: c811a8aaaea089ca2ebaddb559a3ab2fa3ab2a73e2afbcc485e2375654735a6a68ba20fcbc95e0483ba65c83fed367d449289ee79020522887d418e1e9a0a0fb
6
+ metadata.gz: 7f6d08a9ea9be426cd26e67fcbfa96bc4051b83aa9d38837f77fda2f9715a84e766182993a8e1f725fa945ea9c0bbf68f32155827482d7100036e20f02fd9e97
7
+ data.tar.gz: cba999b57e6317c865fc1b98dd56a042b98d2439af5ec8e28ffefd58d52e871513cd7152f640a9d449f1145a870b66ae1fd6d2343376cf0347eb52f8c2373c6d
@@ -9,95 +9,24 @@
9
9
  "value": "https://inferno.healthit.gov/reference-server/r4"
10
10
  },
11
11
  {
12
- "name": "standalone_client_id",
13
- "type": "text",
14
- "value": "SAMPLE_PUBLIC_CLIENT_ID"
15
- },
16
- {
17
- "name": "standalone_requested_scopes",
18
- "type": "text",
19
- "value": "launch/patient openid fhirUser offline_access patient/*.read"
20
- },
21
- {
22
- "name": "use_pkce",
23
- "type": "radio",
24
- "title": "Proof Key for Code Exchange (PKCE)",
25
- "options": {
26
- "list_options": [
27
- {
28
- "label": "Enabled",
29
- "value": "true"
30
- },
31
- {
32
- "label": "Disabled",
33
- "value": "false"
34
- }
35
- ]
36
- },
37
- "value": "false"
38
- },
39
- {
40
- "name": "pkce_code_challenge_method",
41
- "type": "radio",
42
- "optional": true,
43
- "title": "PKCE Code Challenge Method",
44
- "options": {
45
- "list_options": [
46
- {
47
- "label": "S256",
48
- "value": "S256"
49
- },
50
- {
51
- "label": "plain",
52
- "value": "plain"
53
- }
54
- ]
55
- },
56
- "value": "S256"
57
- },
58
- {
59
- "name": "client_auth_type",
60
- "value": "public",
61
- "_title": "Client Authentication Method",
62
- "_type": "radio",
63
- "_options": {
64
- "list_options": [
65
- {
66
- "label": "Public",
67
- "value": "public"
68
- },
69
- {
70
- "label": "Confidential Symmetric",
71
- "value": "confidential_symmetric"
72
- },
73
- {
74
- "label": "Confidential Asymmetric",
75
- "value": "confidential_asymmetric"
76
- }
77
- ]
12
+ "name": "standalone_smart_auth_info",
13
+ "type": "auth_info",
14
+ "value": {
15
+ "auth_type": "public",
16
+ "requested_scopes": "launch/patient openid fhirUser offline_access patient/*.read",
17
+ "client_id": "SAMPLE_PUBLIC_CLIENT_ID",
18
+ "pkce_support": "disabled"
78
19
  }
79
20
  },
80
21
  {
81
- "name": "standalone_client_secret",
82
- "type": "text",
83
- "optional": true,
84
- "value": null
85
- },
86
- {
87
- "name": "ehr_client_id",
88
- "type": "text",
89
- "value": "SAMPLE_PUBLIC_CLIENT_ID"
90
- },
91
- {
92
- "name": "ehr_requested_scopes",
93
- "type": "text",
94
- "value": "launch openid fhirUser offline_access user/*.read"
95
- },
96
- {
97
- "name": "ehr_client_secret",
98
- "type": "text",
99
- "optional": true,
100
- "value": null
22
+ "name": "ehr_smart_auth_info",
23
+ "type": "auth_info",
24
+ "value": {
25
+ "auth_type": "public",
26
+ "requested_scopes": "launch openid fhirUser offline_access user/*.read",
27
+ "client_id": "SAMPLE_PUBLIC_CLIENT_ID",
28
+ "pkce_support": "disabled"
29
+ }
101
30
  }
102
31
  ]
103
32
  }
@@ -9,81 +9,32 @@
9
9
  "value": "https://inferno.healthit.gov/reference-server/r4"
10
10
  },
11
11
  {
12
- "name": "standalone_client_id",
13
- "type": "text",
14
- "value": "SAMPLE_PUBLIC_CLIENT_ID"
15
- },
16
- {
17
- "name": "standalone_requested_scopes",
18
- "type": "text",
19
- "value": "launch/patient openid fhirUser offline_access patient/*.read"
20
- },
21
- {
22
- "name": "standalone_client_secret",
23
- "type": "text",
24
- "optional": true,
25
- "value": null
26
- },
27
- {
28
- "name": "ehr_client_id",
29
- "type": "text",
30
- "value": "SAMPLE_PUBLIC_CLIENT_ID"
31
- },
32
- {
33
- "name": "ehr_requested_scopes",
34
- "type": "text",
35
- "value": "launch openid fhirUser offline_access user/*.read"
36
- },
37
- {
38
- "name": "ehr_client_secret",
39
- "type": "text",
40
- "optional": true,
41
- "value": null
42
- },
43
- {
44
- "name": "client_auth_encryption_method",
45
- "value": "ES384",
46
- "_title": "Encryption Method (Confidential Asymmetric Client Auth Only)",
47
- "_type": "radio",
48
- "_options": {
49
- "list_options": [
50
- {
51
- "label": "ES384",
52
- "value": "ES384"
53
- },
54
- {
55
- "label": "RS384",
56
- "value": "RS384"
57
- }
58
- ]
12
+ "name": "standalone_smart_auth_info",
13
+ "type": "auth_info",
14
+ "value": {
15
+ "auth_type":"public",
16
+ "requested_scopes":"launch/patient openid fhirUser offline_access patient/*.rs",
17
+ "client_id":"SAMPLE_PUBLIC_CLIENT_ID"
59
18
  }
60
19
  },
61
20
  {
62
- "name": "client_auth_type",
63
- "value": "public",
64
- "_title": "Client Authentication Method",
65
- "_type": "radio",
66
- "_options": {
67
- "list_options": [
68
- {
69
- "label": "Public",
70
- "value": "public"
71
- },
72
- {
73
- "label": "Confidential Symmetric",
74
- "value": "confidential_symmetric"
75
- },
76
- {
77
- "label": "Confidential Asymmetric",
78
- "value": "confidential_asymmetric"
79
- }
80
- ]
21
+ "name": "ehr_smart_auth_info",
22
+ "type": "auth_info",
23
+ "value": {
24
+ "auth_type":"public",
25
+ "requested_scopes":"launch openid fhirUser offline_access user/*.rs",
26
+ "client_id":"SAMPLE_PUBLIC_CLIENT_ID"
81
27
  }
82
28
  },
83
29
  {
84
- "name": "backend_services_client_id",
85
- "type": "text",
86
- "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJlZ2lzdHJhdGlvbi10b2tlbiJ9.eyJqd2tzX3VybCI6Imh0dHA6Ly8xMC4xNS4yNTIuNzMvaW5mZXJuby8ud2VsbC1rbm93bi9qd2tzLmpzb24iLCJhY2Nlc3NUb2tlbnNFeHBpcmVJbiI6MTUsImlhdCI6MTU5NzQxMzE5NX0.q4v4Msc74kN506KTZ0q_minyapJw0gwlT6M_uiL73S4"
30
+ "name": "backend_services_smart_auth_info",
31
+ "type": "auth_info",
32
+ "value": {
33
+ "auth_type":"backend_services",
34
+ "requested_scopes":"system/*.read",
35
+ "client_id":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJlZ2lzdHJhdGlvbi10b2tlbiJ9.eyJqd2tzX3VybCI6Imh0dHA6Ly8xMC4xNS4yNTIuNzMvaW5mZXJuby8ud2VsbC1rbm93bi9qd2tzLmpzb24iLCJhY2Nlc3NUb2tlbnNFeHBpcmVJbiI6MTUsImlhdCI6MTU5NzQxMzE5NX0.q4v4Msc74kN506KTZ0q_minyapJw0gwlT6M_uiL73S4",
36
+ "encryption_algorithm":"ES384"
37
+ }
87
38
  }
88
39
  ]
89
40
  }
@@ -9,81 +9,32 @@
9
9
  "value": "https://inferno.healthit.gov/reference-server/r4"
10
10
  },
11
11
  {
12
- "name": "standalone_client_id",
13
- "type": "text",
14
- "value": "SAMPLE_PUBLIC_CLIENT_ID"
15
- },
16
- {
17
- "name": "standalone_requested_scopes",
18
- "type": "text",
19
- "value": "launch/patient openid fhirUser offline_access patient/*.read"
20
- },
21
- {
22
- "name": "standalone_client_secret",
23
- "type": "text",
24
- "optional": true,
25
- "value": null
26
- },
27
- {
28
- "name": "ehr_client_id",
29
- "type": "text",
30
- "value": "SAMPLE_PUBLIC_CLIENT_ID"
31
- },
32
- {
33
- "name": "ehr_requested_scopes",
34
- "type": "text",
35
- "value": "launch openid fhirUser offline_access user/*.read"
36
- },
37
- {
38
- "name": "ehr_client_secret",
39
- "type": "text",
40
- "optional": true,
41
- "value": null
42
- },
43
- {
44
- "name": "client_auth_encryption_method",
45
- "value": "ES384",
46
- "_title": "Encryption Method (Confidential Asymmetric Client Auth Only)",
47
- "_type": "radio",
48
- "_options": {
49
- "list_options": [
50
- {
51
- "label": "ES384",
52
- "value": "ES384"
53
- },
54
- {
55
- "label": "RS384",
56
- "value": "RS384"
57
- }
58
- ]
12
+ "name": "standalone_smart_auth_info",
13
+ "type": "auth_info",
14
+ "value": {
15
+ "auth_type": "public",
16
+ "requested_scopes":"launch/patient openid fhirUser offline_access patient/*.rs",
17
+ "client_id":"SAMPLE_PUBLIC_CLIENT_ID"
59
18
  }
60
19
  },
61
20
  {
62
- "name": "client_auth_type",
63
- "value": "public",
64
- "_title": "Client Authentication Method",
65
- "_type": "radio",
66
- "_options": {
67
- "list_options": [
68
- {
69
- "label": "Public",
70
- "value": "public"
71
- },
72
- {
73
- "label": "Confidential Symmetric",
74
- "value": "confidential_symmetric"
75
- },
76
- {
77
- "label": "Confidential Asymmetric",
78
- "value": "confidential_asymmetric"
79
- }
80
- ]
21
+ "name": "ehr_smart_auth_info",
22
+ "type": "auth_info",
23
+ "value": {
24
+ "auth_type":"public",
25
+ "requested_scopes":"launch openid fhirUser offline_access user/*.rs",
26
+ "client_id":"SAMPLE_PUBLIC_CLIENT_ID"
81
27
  }
82
28
  },
83
29
  {
84
- "name": "backend_services_client_id",
85
- "type": "text",
86
- "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJlZ2lzdHJhdGlvbi10b2tlbiJ9.eyJqd2tzX3VybCI6Imh0dHA6Ly8xMC4xNS4yNTIuNzMvaW5mZXJuby8ud2VsbC1rbm93bi9qd2tzLmpzb24iLCJhY2Nlc3NUb2tlbnNFeHBpcmVJbiI6MTUsImlhdCI6MTU5NzQxMzE5NX0.q4v4Msc74kN506KTZ0q_minyapJw0gwlT6M_uiL73S4"
30
+ "name": "backend_services_smart_auth_info",
31
+ "type": "auth_info",
32
+ "value": {
33
+ "auth_type":"backend_services",
34
+ "requested_scopes":"system/*.read",
35
+ "client_id":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InJlZ2lzdHJhdGlvbi10b2tlbiJ9.eyJqd2tzX3VybCI6Imh0dHA6Ly8xMC4xNS4yNTIuNzMvaW5mZXJuby8ud2VsbC1rbm93bi9qd2tzLmpzb24iLCJhY2Nlc3NUb2tlbnNFeHBpcmVJbiI6MTUsImlhdCI6MTU5NzQxMzE5NX0.q4v4Msc74kN506KTZ0q_minyapJw0gwlT6M_uiL73S4",
36
+ "encryption_algorithm":"ES384"
37
+ }
87
38
  }
88
39
  ]
89
40
  }
@@ -9,41 +9,8 @@ module SMARTAppLaunch
9
9
  )
10
10
  id :smart_app_redirect
11
11
 
12
- input :client_id, :requested_scopes, :url, :smart_authorization_url
13
- input :use_pkce,
14
- title: 'Proof Key for Code Exchange (PKCE)',
15
- type: 'radio',
16
- default: 'false',
17
- options: {
18
- list_options: [
19
- {
20
- label: 'Enabled',
21
- value: 'true'
22
- },
23
- {
24
- label: 'Disabled',
25
- value: 'false'
26
- }
27
- ]
28
- }
29
- input :pkce_code_challenge_method,
30
- optional: true,
31
- title: 'PKCE Code Challenge Method',
32
- type: 'radio',
33
- default: 'S256',
34
- options: {
35
- list_options: [
36
- {
37
- label: 'S256',
38
- value: 'S256'
39
- },
40
- {
41
- label: 'plain',
42
- value: 'plain'
43
- }
44
- ]
45
- }
46
-
12
+ input :url
13
+ input :smart_auth_info, type: :auth_info, options: { mode: 'auth' }
47
14
  output :state, :pkce_code_challenge, :pkce_code_verifier
48
15
  receives_request :redirect
49
16
 
@@ -91,17 +58,17 @@ module SMARTAppLaunch
91
58
 
92
59
  run do
93
60
  assert_valid_http_uri(
94
- smart_authorization_url,
95
- "OAuth2 Authorization Endpoint '#{smart_authorization_url}' is not a valid URI"
61
+ smart_auth_info.auth_url,
62
+ "OAuth2 Authorization Endpoint '#{smart_auth_info.auth_url}' is not a valid URI"
96
63
  )
97
64
 
98
65
  output state: SecureRandom.uuid
99
66
 
100
67
  oauth2_params = {
101
68
  'response_type' => 'code',
102
- 'client_id' => client_id,
69
+ 'client_id' => smart_auth_info.client_id,
103
70
  'redirect_uri' => redirect_uri,
104
- 'scope' => requested_scopes,
71
+ 'scope' => smart_auth_info.requested_scopes,
105
72
  'state' => state,
106
73
  'aud' => aud
107
74
  }
@@ -112,11 +79,11 @@ module SMARTAppLaunch
112
79
  oauth2_params['launch'] = launch
113
80
  end
114
81
 
115
- if use_pkce == 'true'
82
+ if smart_auth_info.pkce_enabled?
116
83
  # code verifier must be between 43 and 128 characters
117
- code_verifier = SecureRandom.uuid + '-' + SecureRandom.uuid
84
+ code_verifier = "#{SecureRandom.uuid}-#{SecureRandom.uuid}"
118
85
  code_challenge =
119
- if pkce_code_challenge_method == 'S256'
86
+ if smart_auth_info.s256_code_challenge_method?
120
87
  self.class.calculate_s256_challenge(code_verifier)
121
88
  else
122
89
  code_verifier
@@ -124,11 +91,12 @@ module SMARTAppLaunch
124
91
 
125
92
  output pkce_code_verifier: code_verifier, pkce_code_challenge: code_challenge
126
93
 
127
- oauth2_params.merge!('code_challenge' => code_challenge, 'code_challenge_method' => pkce_code_challenge_method)
94
+ oauth2_params.merge!('code_challenge' => code_challenge,
95
+ 'code_challenge_method' => smart_auth_info.pkce_code_challenge_method)
128
96
  end
129
97
 
130
98
  authorization_url = authorization_url_builder(
131
- smart_authorization_url,
99
+ smart_auth_info.auth_url,
132
100
  oauth2_params
133
101
  )
134
102
 
@@ -15,22 +15,7 @@ module SMARTAppLaunch
15
15
  Request](http://hl7.org/fhir/smart-app-launch/STU2/app-launch.html#request-4)
16
16
  )
17
17
 
18
- input :authorization_method,
19
- title: 'Authorization Request Method',
20
- type: 'radio',
21
- default: 'get',
22
- options: {
23
- list_options: [
24
- {
25
- label: 'GET',
26
- value: 'get'
27
- },
28
- {
29
- label: 'POST',
30
- value: 'post'
31
- }
32
- ]
33
- }
18
+ input :smart_auth_info, type: :auth_info, options: { mode: 'auth' }
34
19
 
35
20
  def default_post_authorization_uri
36
21
  "#{Inferno::Application['base_url']}/custom/smart_stu2/post_auth"
@@ -41,7 +26,7 @@ module SMARTAppLaunch
41
26
  end
42
27
 
43
28
  def authorization_url_builder(url, params)
44
- return super if authorization_method == 'get'
29
+ return super if smart_auth_info.get_auth_request?
45
30
 
46
31
  post_params = params.merge(auth_url: url)
47
32
 
@@ -13,67 +13,43 @@ module SMARTAppLaunch
13
13
 
14
14
  id :backend_services_authorization
15
15
 
16
- input :smart_token_url,
17
- title: 'Backend Services Token Endpoint',
18
- description: <<~DESCRIPTION
19
- The OAuth 2.0 Token Endpoint used by the Backend Services specification to provide bearer tokens.
20
- DESCRIPTION
21
-
22
- input :backend_services_client_id,
23
- title: 'Backend Services Client ID',
24
- description: 'Client ID provided at registration to the Inferno application.'
25
- input :backend_services_requested_scope,
26
- title: 'Backend Services Requested Scopes',
27
- description: 'Backend Services Scopes provided at registration to the Inferno application; will be `system/` scopes',
28
- default: 'system/*.read'
29
-
30
- input :client_auth_encryption_method,
31
- title: 'Encryption Method for Asymmetric Confidential Client Authorization',
32
- description: <<~DESCRIPTION,
33
- The server is required to suport either ES384 or RS384 encryption methods for JWT signature verification.
34
- Select which method to use.
35
- DESCRIPTION
36
- type: 'radio',
37
- default: 'ES384',
38
- options: {
39
- list_options: [
40
- {
41
- label: 'ES384',
42
- value: 'ES384'
43
- },
44
- {
45
- label: 'RS384',
46
- value: 'RS384'
16
+ input :smart_auth_info,
17
+ title: 'Backend Services Credentials',
18
+ type: :auth_info,
19
+ options: {
20
+ mode: 'auth',
21
+ components: [
22
+ {
23
+ name: :auth_type,
24
+ default: 'backend_services',
25
+ locked: 'true'
26
+ },
27
+ {
28
+ name: :use_discovery,
29
+ locked: true
30
+ }
31
+ ]
47
32
  }
48
- ]
49
- }
50
- input :backend_services_jwks_kid,
51
- title: 'Backend Services JWKS kid',
52
- description: <<~DESCRIPTION,
53
- The key ID of the JWKS private key to use for signing the client assertion when fetching an auth token.
54
- Defaults to the first JWK in the list if no kid is supplied.
55
- DESCRIPTION
56
- optional: true
57
33
 
58
34
  output :bearer_token
59
35
 
60
- test from: :tls_version_test do
61
- title 'Authorization service token endpoint secured by transport layer security'
62
- description <<~DESCRIPTION
63
- The [SMART App Launch 2.0.0 IG specification for Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#request-1)
64
- states "the client SHALL use the Transport Layer Security (TLS) Protocol Version 1.2 (RFC5246)
65
- or a more recent version of TLS to authenticate the identity of the FHIR authorization server and to
66
- establish an encrypted, integrity-protected link for securing all exchanges between the client and the
67
- FHIR authorization server’s token endpoint. All exchanges described herein between the client and the
68
- FHIR server SHALL be secured using TLS V1.2 or a more recent version of TLS."
69
- DESCRIPTION
70
- id :smart_backend_services_token_tls_version
71
-
72
- config(
73
- inputs: { url: { name: :smart_token_url } },
74
- options: { minimum_allowed_version: OpenSSL::SSL::TLS1_2_VERSION }
75
- )
76
- end
36
+ test from: :smart_tls,
37
+ id: :smart_backend_services_token_tls_version,
38
+ title: 'Authorization service token endpoint secured by transport layer security',
39
+ description: <<~DESCRIPTION,
40
+ The [SMART App Launch 2.0.0 IG specification for Backend Services](https://hl7.org/fhir/smart-app-launch/STU2/backend-services.html#request-1)
41
+ states "the client SHALL use the Transport Layer Security (TLS) Protocol Version 1.2 (RFC5246)
42
+ or a more recent version of TLS to authenticate the identity of the FHIR authorization server and to
43
+ establish an encrypted, integrity-protected link for securing all exchanges between the client and the
44
+ FHIR authorization server’s token endpoint. All exchanges described herein between the client and the
45
+ FHIR server SHALL be secured using TLS V1.2 or a more recent version of TLS."
46
+ DESCRIPTION
47
+ config: {
48
+ options: {
49
+ minimum_allowed_version: OpenSSL::SSL::TLS1_2_VERSION,
50
+ smart_endpoint_key: :token_url
51
+ }
52
+ }
77
53
 
78
54
  test from: :smart_backend_services_invalid_grant_type
79
55
 
@@ -7,8 +7,18 @@ module SMARTAppLaunch
7
7
  new(...).authorization_request
8
8
  end
9
9
 
10
- attr_reader :encryption_method, :scope, :iss, :sub, :aud, :content_type, :grant_type, :client_assertion_type, :exp,
11
- :jti, :kid
10
+ attr_reader :encryption_method,
11
+ :scope,
12
+ :iss,
13
+ :sub,
14
+ :aud,
15
+ :content_type,
16
+ :grant_type,
17
+ :client_assertion_type,
18
+ :exp,
19
+ :jti,
20
+ :kid,
21
+ :custom_jwks
12
22
 
13
23
  def initialize(
14
24
  encryption_method:,
@@ -21,7 +31,8 @@ module SMARTAppLaunch
21
31
  client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
22
32
  exp: 5.minutes.from_now,
23
33
  jti: SecureRandom.hex(32),
24
- kid: nil
34
+ kid: nil,
35
+ custom_jwks: nil
25
36
  )
26
37
  @encryption_method = encryption_method
27
38
  @scope = scope
@@ -34,6 +45,7 @@ module SMARTAppLaunch
34
45
  @exp = exp
35
46
  @jti = jti
36
47
  @kid = kid
48
+ @custom_jwks = custom_jwks
37
49
  end
38
50
 
39
51
  def authorization_request_headers
@@ -54,13 +66,14 @@ module SMARTAppLaunch
54
66
 
55
67
  def client_assertion
56
68
  @client_assertion ||= ClientAssertionBuilder.build(
57
- client_auth_encryption_method: encryption_method,
58
- iss: iss,
59
- sub: sub,
60
- aud: aud,
69
+ client_auth_encryption_method: encryption_method,
70
+ iss:,
71
+ sub:,
72
+ aud:,
61
73
  exp: exp.to_i,
62
- jti: jti,
63
- kid: kid
74
+ jti:,
75
+ kid:,
76
+ custom_jwks:
64
77
  )
65
78
  end
66
79