udap_security_test_kit 0.11.3 → 0.11.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/config/presets/UDAP_RunServerAgainstClient.json.erb +4 -4
  3. data/lib/udap_security_test_kit/client_suite/access_ac_group.rb +25 -0
  4. data/lib/udap_security_test_kit/client_suite/access_ac_interaction_test.rb +59 -0
  5. data/lib/udap_security_test_kit/client_suite/access_cc_group.rb +23 -0
  6. data/lib/udap_security_test_kit/client_suite/access_cc_interaction_test.rb +49 -0
  7. data/lib/udap_security_test_kit/client_suite/authorization_request_verification_test.rb +83 -0
  8. data/lib/udap_security_test_kit/client_suite/client_descriptions.rb +70 -0
  9. data/lib/udap_security_test_kit/client_suite/client_options.rb +20 -0
  10. data/lib/udap_security_test_kit/client_suite/oidc_jwks.json +32 -0
  11. data/lib/udap_security_test_kit/client_suite/oidc_jwks.rb +27 -0
  12. data/lib/udap_security_test_kit/client_suite/registration_ac_group.rb +18 -0
  13. data/lib/udap_security_test_kit/client_suite/registration_ac_verification_test.rb +38 -0
  14. data/lib/udap_security_test_kit/client_suite/registration_cc_group.rb +18 -0
  15. data/lib/udap_security_test_kit/client_suite/registration_cc_verification_test.rb +38 -0
  16. data/lib/udap_security_test_kit/client_suite/{client_registration_interaction_test.rb → registration_interaction_test.rb} +11 -4
  17. data/lib/udap_security_test_kit/client_suite/{client_registration_verification_test.rb → registration_request_verification.rb} +38 -40
  18. data/lib/udap_security_test_kit/client_suite/token_request_ac_verification_test.rb +49 -0
  19. data/lib/udap_security_test_kit/client_suite/token_request_cc_verification_test.rb +49 -0
  20. data/lib/udap_security_test_kit/client_suite/{client_token_request_verification_test.rb → token_request_verification.rb} +91 -46
  21. data/lib/udap_security_test_kit/client_suite/{client_token_use_verification_test.rb → token_use_verification_test.rb} +0 -3
  22. data/lib/udap_security_test_kit/client_suite.rb +46 -17
  23. data/lib/udap_security_test_kit/docs/udap_client_suite_description.md +74 -31
  24. data/lib/udap_security_test_kit/endpoints/echoing_fhir_responder_endpoint.rb +96 -0
  25. data/lib/udap_security_test_kit/endpoints/mock_udap_server/authorization_endpoint.rb +28 -0
  26. data/lib/udap_security_test_kit/endpoints/mock_udap_server/registration_endpoint.rb +31 -0
  27. data/lib/udap_security_test_kit/endpoints/mock_udap_server/token_endpoint.rb +56 -0
  28. data/lib/udap_security_test_kit/endpoints/mock_udap_server/udap_authorization_response_creation.rb +63 -0
  29. data/lib/udap_security_test_kit/endpoints/mock_udap_server/udap_registration_response_creation.rb +28 -0
  30. data/lib/udap_security_test_kit/endpoints/mock_udap_server/udap_token_response_creation.rb +218 -0
  31. data/lib/udap_security_test_kit/endpoints/mock_udap_server.rb +112 -31
  32. data/lib/udap_security_test_kit/metadata.rb +1 -1
  33. data/lib/udap_security_test_kit/tags.rb +4 -0
  34. data/lib/udap_security_test_kit/urls.rb +15 -8
  35. data/lib/udap_security_test_kit/version.rb +2 -2
  36. metadata +28 -12
  37. data/lib/udap_security_test_kit/client_suite/client_access_group.rb +0 -22
  38. data/lib/udap_security_test_kit/client_suite/client_access_interaction_test.rb +0 -53
  39. data/lib/udap_security_test_kit/client_suite/client_registration_group.rb +0 -26
  40. data/lib/udap_security_test_kit/endpoints/echoing_fhir_responder.rb +0 -52
  41. data/lib/udap_security_test_kit/endpoints/mock_udap_server/registration.rb +0 -57
  42. data/lib/udap_security_test_kit/endpoints/mock_udap_server/token.rb +0 -27
@@ -9,8 +9,11 @@ client systems to the STU 1.0.0 version of the HL7® FHIR®
9
9
  The UDAP Security Client Test Suite verifies that systems correctly implement
10
10
  the [UDAP Security IG](https://hl7.org/fhir/us/udap-security/STU1/)
11
11
  for authorizating and/or authenticating with a server in order to gain
12
- access to HL7® FHIR® APIs. At this time, the suite only contains tests for
13
- the [Business-to-Business Client Credentials flow](https://hl7.org/fhir/us/udap-security/STU1/b2b.html).
12
+ access to HL7® FHIR® APIs. The suite contains options for testing clients that follow the
13
+ - Authorization Code flow for [consumer facing](https://hl7.org/fhir/us/udap-security/STU1/consumer.html)
14
+ or [Business-to-Business](https://hl7.org/fhir/us/udap-security/STU1/b2b.html) access.
15
+ - Client Credentials flow for [Business-to-Business](https://hl7.org/fhir/us/udap-security/STU1/b2b.html)
16
+ access.
14
17
 
15
18
  These tests are a **DRAFT** intended to allow implementers to perform
16
19
  preliminary checks of their systems against UDAP Security IG
@@ -20,8 +23,8 @@ requirements and may change the test verification logic.
20
23
 
21
24
  ## Test Methodology
22
25
 
23
- For these tests Inferno simulates a UDAP server that supports the business-to-business
24
- client credentials flow. Testers will
26
+ For these tests Inferno simulates a UDAP server that supports both the authorization code
27
+ and the client credentials flows. In both cases, testers will
25
28
  1. Provide to Inferno the client URI with which they will register their system.
26
29
  2. Make a dynamic registration request to Inferno using the provided client URI
27
30
  and including the X.509 certificate used to sign the registeration and subsequent
@@ -59,24 +62,26 @@ steps use [Postman](https://www.postman.com/) to generate the access request usi
59
62
  [this collection](https://github.com/inferno-framework/udap-security-test-kit/blob/main/lib/udap_security_test_kit/docs/demo/FHIR%20Request.postman_collection.json).
60
63
  Install the app and import the collection before following these steps.
61
64
 
62
- 1. Start an instance of the UDAP Security Client test suite.
63
- 2. From the drop down in the upper left, select preset "Demo: Run Against the UDAP Security Server Suite".
64
- 3. Click the "RUN ALL TESTS" button in the upper right and click "SUBMIT"
65
- 4. In a new tab, start an instance of the UDAP Security Server Test Suite
66
- 5. From the drop down in the upper left, select preset "Demo: Run Against the UDAP Security Client Suite"
67
- 6. Select test group **2** UDAP Client Credentials Flow from the left panel, click the "RUN ALL TESTS" button
68
- in the upper right, and click "SUBMIT"
69
- 7. In the Client suite tab, click the link in the wait dialog to continue the tests.
70
- 8. In the Server suite tab, find the access token to use for the data access request by opening
71
- test **2.3.01** OAuth token exchange request succeeds when supplied correct information, click
72
- on the "REQUESTS" tab, clicking on the "DETAILS" button, and expanding the "Response Body".
65
+ 1. Start an instance of the UDAP Security Client test suite and choose either option: *Authorization Code*,
66
+ or *Client Credentials* flow. Remember your choice for use later.
67
+ 1. From the drop down in the upper left, select preset "Demo: Run Against the UDAP Security Server Suite".
68
+ 1. Click the "RUN ALL TESTS" button in the upper right and click "SUBMIT"
69
+ 1. In a new tab, start an instance of the UDAP Security Server Test Suite
70
+ 1. From the drop down in the upper left, select preset "Demo: Run Against the UDAP Security Client Suite"
71
+ 1. Select the test group corresponding to your choice in step 1: **1** for *Authorization Code* and **2**
72
+ for *Client Credentials*. Click the "RUN ALL TESTS" button in the upper right, and click "SUBMIT".
73
+ 1. If testing the *Authorization Code* flow, click the link to authorize with the server.
74
+ 1. In the Client suite tab, click the link in the wait dialog to continue the tests.
75
+ 1. In the Server suite tab, find the access token to use for the data access request by opening
76
+ test **1.3.03** or **2.3.01** OAuth token exchange request succeeds when supplied correct information,
77
+ click on the "REQUESTS" tab, clicking on the "DETAILS" button, and expanding the "Response Body".
73
78
  Copy the "access_token" value, which will be a ~100 character string of letters and numbers (e.g., eyJjbGllbnRfaWQiOiJzbWFydF9jbGllbnRfdGVzdF9kZW1vIiwiZXhwaXJhdGlvbiI6MTc0MzUxNDk4Mywibm9uY2UiOiJlZDI5MWIwNmZhMTE4OTc4In0)
74
- 9. Open Postman and open the "FHIR Request" Collection. Click the "Variables" tab and add the
79
+ 1. Open Postman and open the "FHIR Request" Collection. Click the "Variables" tab and add the
75
80
  copied access token as the current value of the `bearer_token` variable. Also update the
76
81
  `base_url` value for where the test is running (see details on the "Overview" tab).
77
82
  Save the collection.
78
- 10. Select the "Patient Read" request and click "Send". A FHIR Patient resource should be returned.
79
- 11. Return to the client tests and click the link to continue and complete the tests.
83
+ 1. Select the "Patient Read" request and click "Send". A FHIR Patient resource should be returned.
84
+ 1. Return to the client tests and click the link to continue and complete the tests.
80
85
 
81
86
  The client tests should pass. On the server side some of the registration tests will fail. This is
82
87
  expected as the Server tests make several intentionally invalid token requests. Inferno's simulated UDAP
@@ -86,20 +91,58 @@ registration requests is itself not conformant there are corresponding failures
86
91
 
87
92
  ### Additional Inputs
88
93
 
89
- One additional input is available to support testers
90
- - **FHIR Response to Echo**: The focus of this test kit is on the auth protocol, so the
91
- simulated FHIR server implemented in this test suite is very simple and will by default
92
- return a FHIR OperationOutcome to any request made. Testers may provide a static
93
- FHIR JSON body for Inferno to return instead. In this case, the simulation is a simple
94
- echo and Inferno does not check that the response if appropriate for the request made.
94
+ #### Inputs Controlling Token Responses
95
+
96
+ The UDAP simulation incorporates some aspects of SMART App launch including its approach to
97
+ [context data](https://hl7.org/fhir/smart-app-launch/STU2.2/scopes-and-launch-context.html)
98
+ in token responses during the authorization code flow.
99
+ Inferno's SMART simulation does not include the details needed to populate
100
+ these details into the token response when requested by apps using scopes.
101
+ If the tested app needs and will request these details, the tester must provide them for Inferno
102
+ to respond with using the following inputs:
103
+ - **Launch Context** (available for all *SMART App Launch* clients): Testers can provide a JSON
104
+ array for Inferno to use as the base for building a token response on. This can include
105
+ keys like `"patient"` when the `launch/patient` scope will be requested. Note that when keys that Inferno
106
+ also populates (e.g. `access_token` or `id_token`) are included, the Inferno value will be returned.
107
+ - **FHIR User Relative Reference** (available for all *SMART App Launch* clients): Testers
108
+ can provide a FHIR relative reference (`<resource type>/<id>`) for the FHIR user record
109
+ to return with the `id_token` when the `openid` and `fhirUser` scopes are requested. If populated,
110
+ include the corresponding resource in the **Available Resources** input (See the "Inputs
111
+ Controlling FHIR Responses" section) so that it can be accessed via FHIR read.
112
+
113
+ #### Inputs Controlling FHIR Responses
114
+ The focus of this test kit is on the auth protocol, so the simulated FHIR server implemented
115
+ in this test suite is very simple. It will respond to any FHIR request with either:
116
+ - A resource from a tester-provided Bundle in the **Available Resources** input
117
+ if the request is a read matching a resource type and id found in the Bundle.
118
+ - Otherwise, the contents of the **Default FHIR Response** input, if provided.
119
+ - Otherwise, an OperationOutcome indicating no response was available.
120
+
121
+ The two inputs that control these response include:
122
+ - **Available Resources**: A FHIR Bundle of resources to make available via the
123
+ simulated FHIR sever. Each entry must contain a resource with the id element
124
+ populated. Each instance present will be available for retrieval from Inferno
125
+ at the endpoint: `<fhir-base>/<resource type>/<instance id>`. These will only
126
+ be available through the read interaction.
127
+ - **FHIR Response to Echo**: A static FHIR JSON body for Inferno to return for all FHIR requests
128
+ not covered by reads of instances in the **Available Resources** input. In this case,
129
+ the simulation is a simple echo and Inferno does not check that the response is
130
+ appropriate for the request made.
95
131
 
96
132
  ## Current Limitations
97
133
 
98
134
  This test kit is still in draft form and does not test all of the requirements and features
99
- described in the UDAP Security IG for clients. Notably, only the B2B client credentials flow
100
- is tested at this time.
135
+ described in the UDAP Security IG for clients.
101
136
 
102
- The following sections list other known gaps and limitations.
137
+ The following sections list known gaps and limitations.
138
+
139
+ ### SMART Scope Checking and Fulfilment
140
+
141
+ These tests do not verify any details about scopes, including that the
142
+ - Requested scopes are conformant, such as that they have a valid format and are consistent
143
+ between authorization and refresh token requests.
144
+ - Provided **Launch Context** input fullfils the requested data context scopes.
145
+ - Access performed is allowed by the requested scope.
103
146
 
104
147
  ### UDAP Server Simulation Limitations
105
148
 
@@ -114,7 +157,7 @@ systems from passing in the [github repository's issues page](https://github.com
114
157
  ### FHIR Server Simulation Limitations
115
158
 
116
159
  The FHIR server simulation used to support clients in demonstrating their ability to access
117
- FHIR APIs using access tokens obtained using the UDAP flows is very limited. Testers are currently
118
- able to provide a single static response that will be echoed for any FHIR request made. While
119
- Inferno will never implement a fully general FHIR server simulation, additional options may be added
120
- in the future based on community feedback.
160
+ FHIR APIs using access tokens obtained using the SMART flows is very limited. Testers are currently
161
+ able to provide a list of resources to be read and a single static response that will be echoed for any
162
+ other FHIR request made. While Inferno will never implement a fully general FHIR server simulation,
163
+ additional options, such as may be added in the future based on community feedback.
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../urls'
4
+ require_relative '../tags'
5
+ require_relative 'mock_udap_server'
6
+
7
+ module UDAPSecurityTestKit
8
+ class EchoingFHIRResponderEndpoint < Inferno::DSL::SuiteEndpoint
9
+ def test_run_identifier
10
+ MockUDAPServer.issued_token_to_client_id(request.headers['authorization']&.delete_prefix('Bearer '))
11
+ end
12
+
13
+ def make_response
14
+ return if response.status == 401 # set in update_result (expired token handling there)
15
+
16
+ response.content_type = 'application/fhir+json'
17
+ response.headers['Access-Control-Allow-Origin'] = '*'
18
+ response.status = 200
19
+
20
+ # look for read of provided resources
21
+ read_response = tester_provided_read_response_body
22
+ if read_response.present?
23
+ response.body = read_response.to_json
24
+ return
25
+ end
26
+
27
+ # If the tester provided a response, echo it
28
+ # otherwise, operation outcome
29
+ echo_response = JSON.parse(result.input_json)
30
+ .find { |input| input['name'].include?('echoed_fhir_response') }
31
+ &.dig('value')
32
+ if echo_response.present?
33
+ response.body = echo_response
34
+ return
35
+ end
36
+
37
+ response.status = 400
38
+ response.body = FHIR::OperationOutcome.new(
39
+ issue: FHIR::OperationOutcome::Issue.new(
40
+ severity: 'fatal', code: 'required',
41
+ details: FHIR::CodeableConcept.new(text: 'No response provided to echo.')
42
+ )
43
+ ).to_json
44
+ end
45
+
46
+ def update_result
47
+ if MockUDAPServer.request_has_expired_token?(request)
48
+ MockUDAPServer.update_response_for_expired_token(response, 'Bearer token')
49
+ return
50
+ end
51
+
52
+ nil # never update for now
53
+ end
54
+
55
+ def tags
56
+ [ACCESS_TAG]
57
+ end
58
+
59
+ def tester_provided_read_response_body
60
+ resource_type = request.params[:one]
61
+ id = request.params[:two]
62
+
63
+ return unless resource_type.present? && id.present?
64
+
65
+ resource_type_class =
66
+ begin
67
+ FHIR.const_get(resource_type)
68
+ rescue NameError
69
+ nil
70
+ end
71
+ return unless resource_type_class.present?
72
+
73
+ resource_bundle = ehr_input_bundle
74
+ return unless resource_bundle.present?
75
+
76
+ find_resource_in_bundle(resource_bundle, resource_type_class, id)
77
+ end
78
+
79
+ def ehr_input_bundle
80
+ ehr_bundle_input =
81
+ JSON.parse(result.input_json).find { |input| input['name'] == 'fhir_read_resources_bundle' }&.dig('value')
82
+ ehr_bundle = FHIR.from_contents(ehr_bundle_input) if ehr_bundle_input.present?
83
+ return ehr_bundle if ehr_bundle.is_a?(FHIR::Bundle)
84
+
85
+ nil
86
+ rescue StandardError
87
+ nil
88
+ end
89
+
90
+ def find_resource_in_bundle(bundle, resource_type_class, id)
91
+ bundle.entry&.find do |entry|
92
+ entry.resource.is_a?(resource_type_class) && entry.resource.id == id
93
+ end&.resource
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../tags'
4
+ require_relative 'udap_authorization_response_creation'
5
+
6
+ module UDAPSecurityTestKit
7
+ module MockUDAPServer
8
+ class AuthorizationEndpoint < Inferno::DSL::SuiteEndpoint
9
+ include UDAPAuthorizationResponseCreation
10
+
11
+ def test_run_identifier
12
+ request.params[:client_id]
13
+ end
14
+
15
+ def make_response
16
+ make_udap_authorization_response
17
+ end
18
+
19
+ def update_result
20
+ nil # never update for now
21
+ end
22
+
23
+ def tags
24
+ [AUTHORIZATION_TAG, AUTHORIZATION_CODE_TAG, UDAP_TAG]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../tags'
4
+ require_relative '../mock_udap_server'
5
+ require_relative 'udap_registration_response_creation'
6
+
7
+ module UDAPSecurityTestKit
8
+ module MockUDAPServer
9
+ class RegistrationEndpoint < Inferno::DSL::SuiteEndpoint
10
+ include UDAPRegistrationResponseCreation
11
+
12
+ def test_run_identifier
13
+ MockUDAPServer.client_uri_to_client_id(
14
+ MockUDAPServer.udap_client_uri_from_registration_payload(MockUDAPServer.parsed_io_body(request))
15
+ )
16
+ end
17
+
18
+ def make_response
19
+ make_udap_registration_response
20
+ end
21
+
22
+ def update_result
23
+ nil # never update for now
24
+ end
25
+
26
+ def tags
27
+ [REGISTRATION_TAG, UDAP_TAG]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../tags'
4
+ require_relative '../../urls'
5
+ require_relative '../mock_udap_server'
6
+ require_relative 'udap_token_response_creation'
7
+
8
+ module UDAPSecurityTestKit
9
+ module MockUDAPServer
10
+ class TokenEndpoint < Inferno::DSL::SuiteEndpoint
11
+ include UDAPTokenResponseCreation
12
+ include URLs
13
+
14
+ def test_run_identifier
15
+ case request.params[:grant_type]
16
+ when CLIENT_CREDENTIALS_TAG
17
+ MockUDAPServer.client_id_from_client_assertion(request.params[:client_assertion])
18
+ when AUTHORIZATION_CODE_TAG
19
+ MockUDAPServer.issued_token_to_client_id(request.params[:code])
20
+ when REFRESH_TOKEN_TAG
21
+ MockUDAPServer.issued_token_to_client_id(
22
+ MockUDAPServer.refresh_token_to_authorization_code(request.params[:refresh_token])
23
+ )
24
+ end
25
+ end
26
+
27
+ def make_response
28
+ case request.params[:grant_type]
29
+ when CLIENT_CREDENTIALS_TAG
30
+ make_udap_client_credential_token_response
31
+ when AUTHORIZATION_CODE_TAG
32
+ make_udap_authorization_code_token_response
33
+ when REFRESH_TOKEN_TAG
34
+ make_udap_refresh_token_response
35
+ else
36
+ MockUDAPServer.update_response_for_error(
37
+ response,
38
+ "unsupported grant_type: #{request.params[:grant_type]}"
39
+ )
40
+ end
41
+ end
42
+
43
+ def update_result
44
+ nil # never update for now
45
+ end
46
+
47
+ def tags
48
+ tags = [TOKEN_TAG, UDAP_TAG]
49
+ if [CLIENT_CREDENTIALS_TAG, AUTHORIZATION_CODE_TAG, REFRESH_TOKEN_TAG].include?(request.params[:grant_type])
50
+ tags << request.params[:grant_type]
51
+ end
52
+ tags
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,63 @@
1
+ require 'jwt'
2
+ require_relative '../mock_udap_server'
3
+
4
+ module UDAPSecurityTestKit
5
+ module MockUDAPServer
6
+ module UDAPAuthorizationResponseCreation
7
+ def make_udap_authorization_response
8
+ redirect_uri = request.params[:redirect_uri]
9
+ registered_redirect_uri_list = udap_registered_redirect_uris
10
+
11
+ if redirect_uri.blank?
12
+ # need one from the registered list
13
+ if registered_redirect_uri_list.blank?
14
+ response.status = 400
15
+ response.body = {
16
+ error: 'Bad request',
17
+ message: 'Missing required redirect_uri parameter with no default provided in the registration.'
18
+ }.to_json
19
+ response.content_type = 'application/json'
20
+ return
21
+ elsif registered_redirect_uri_list.length > 1
22
+ response.status = 400
23
+ response.body = {
24
+ error: 'Bad request',
25
+ message: 'Missing required redirect_uri parameter with multiple options provided in the registration.'
26
+ }.to_json
27
+ response.content_type = 'application/json'
28
+ return
29
+ else
30
+ redirect_uri = registered_redirect_uri_list.first
31
+ end
32
+ end
33
+
34
+ client_id = request.params[:client_id]
35
+ state = request.params[:state]
36
+
37
+ exp_min = 10
38
+ token = MockUDAPServer.client_id_to_token(client_id, exp_min)
39
+ code_query_string = "code=#{ERB::Util.url_encode(token)}"
40
+ query_string =
41
+ if state.present?
42
+ "#{code_query_string}&state=#{ERB::Util.url_encode(state)}"
43
+ else
44
+ code_query_string
45
+ end
46
+ response.headers['Location'] = "#{redirect_uri}#{redirect_uri.include?('?') ? '&' : '?'}#{query_string}"
47
+ response.status = 302
48
+ end
49
+
50
+ def udap_registered_redirect_uris
51
+ registered_software_statement = MockUDAPServer.udap_registration_software_statement(test_run.test_session_id)
52
+ return unless registered_software_statement.present?
53
+
54
+ registration_jwt_body, _registration_jwt_header = JWT.decode(registered_software_statement, nil, false)
55
+ return [] unless registration_jwt_body['redirect'].present?
56
+ return registration_jwt_body['redirect'] if registration_jwt_body['redirect'].is_a?(Array)
57
+
58
+ # invalid registration, but we'll succeed here and fail during registration verification
59
+ [registration_jwt_body['redirect']]
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,28 @@
1
+ require_relative '../mock_udap_server'
2
+
3
+ module UDAPSecurityTestKit
4
+ module MockUDAPServer
5
+ module UDAPRegistrationResponseCreation
6
+ def make_udap_registration_response
7
+ parsed_body = MockUDAPServer.parsed_io_body(request)
8
+ client_id = MockUDAPServer.client_uri_to_client_id(
9
+ MockUDAPServer.udap_client_uri_from_registration_payload(parsed_body)
10
+ )
11
+ ss_jwt = MockUDAPServer.udap_software_statement_jwt(parsed_body)
12
+
13
+ response_body = {
14
+ client_id:,
15
+ software_statement: ss_jwt
16
+ }
17
+ response_body.merge!(MockUDAPServer.jwt_claims(ss_jwt).except(['iss', 'sub', 'exp', 'iat', 'jti']))
18
+
19
+ response.body = response_body.to_json
20
+ response.headers['Cache-Control'] = 'no-store'
21
+ response.headers['Pragma'] = 'no-cache'
22
+ response.headers['Access-Control-Allow-Origin'] = '*'
23
+ response.content_type = 'application/json'
24
+ response.status = 201
25
+ end
26
+ end
27
+ end
28
+ end