Skip to content
2 changes: 2 additions & 0 deletions lib/udap_security_test_kit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_relative 'udap_security_test_kit/client_credentials_group'
require_relative 'udap_security_test_kit/redirect_uri'
require_relative 'udap_security_test_kit/metadata'
require_relative 'udap_security_test_kit/visual_inspection_and_attestation/server_attestation_group'

module UDAPSecurityTestKit
class Suite < Inferno::TestSuite
Expand Down Expand Up @@ -93,5 +94,6 @@ class Suite < Inferno::TestSuite

group from: :udap_authorization_code_group
group from: :udap_client_credentials_group
group from: :udap_server_v100_visual_inspection_and_attestation
end
end
3 changes: 3 additions & 0 deletions lib/udap_security_test_kit/client_suite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
require_relative 'client_suite/registration_cc_group'
require_relative 'client_suite/access_ac_group'
require_relative 'client_suite/access_cc_group'
require_relative 'visual_inspection_and_attestation/client_attestation_group'

module UDAPSecurityTestKit
class UDAPSecurityClientTestSuite < Inferno::TestSuite
Expand Down Expand Up @@ -113,5 +114,7 @@ class UDAPSecurityClientTestSuite < Inferno::TestSuite
required_suite_options: {
client_type: UDAPClientOptions::UDAP_CLIENT_CREDENTIALS
}

group from: :udap_client_v100_visual_inspection_and_attestation
end
end

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module UDAPSecurityTestKit
class AuthorizationCodeUsageAttestationTest < Inferno::Test
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class name is duplicated, which is causing the code to fail to run.
This class name must be unique.

title 'Authorization code is used correctly'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per discussion, make titles verb first: "Uses authorization code correctly"

Change throughout

id :udap_security_client_auth_code_usage
description %(
Client applications SHALL use the authorization code correctly by:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per discussion, description here should align with the input description, removing "I attest..." text.

Change throughout.

- Ensuring the authorization code is not used more than once.
- Requesting an authorization code as per Section 4.1.1 of RFC 6749.
)
verifies_requirements 'hl7.fhir.us.udap-security@136',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hl7.fhir.us.udap-security should be hl7.fhir.us.udap-security_1.0.0

You can see this in the excel file in the metadata tab:

image

It's also referenced in the suite lib/udap_security_test_kit.rb:

    requirement_sets(
      {
        identifier: 'hl7.fhir.us.udap-security_1.0.0',
        title: 'Security for Scalable Registration, Authentication, and Authorization (UDAP)',
        actor: 'Server'
      }
    )

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way to check that you're referencing things as expected is to look at the coverage document lib/udap_security_test_kit/requirements/generated/udap_security_client_requirements_coverage.csv. You can see in the client coverage document that there are no test ids associated with these requirements ids
image

'hl7.fhir.us.udap-security@188'

input :authorization_code_usage_correctly,
title: "Authorization code is used correctly",
description: %(
I attest that the client application uses the authorization code correctly by:
- Ensuring the authorization code is not used more than once.
- Requesting an authorization code as per Section 4.1.1 of RFC 6749.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :authorization_code_usage_correctly_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert authorization_code_usage_correctly == 'true',
'Client application did not demonstrate correct usage of the authorization code.'
pass authorization_code_usage_correctly_note if authorization_code_usage_correctly_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
module UDAPSecurityTestKit
class B2BAuthorizationExtensionObjectAttestationTest < Inferno::Test
title 'B2B Authorization Extension Object Compliance'
id :udap_security_b2b_authorization_extension_object
description %(
Client applications SHALL comply with the requirements for the B2B Authorization Extension Object:
- `subject_name` SHALL be required if known for human or non-human requestors.
- `subject_id` SHALL be required if known for human requestors when `subject_name` is present.
- `subject_id` SHALL be the National Provider Identifier (NPI) for US Realm human requestors.
- `subject_id` SHALL be omitted for non-human requestors or requestors without an NPI.
- `consent_reference` SHALL include resolvable URLs and SHALL be omitted if `consent_policy` is not present.
)
verifies_requirements 'hl7.fhir.us.udap-security@203',
'hl7.fhir.us.udap-security@204',
'hl7.fhir.us.udap-security@205',
'hl7.fhir.us.udap-security@206',
'hl7.fhir.us.udap-security@207',
'hl7.fhir.us.udap-security@219',
'hl7.fhir.us.udap-security@220',
'hl7.fhir.us.udap-security@221'

input :subject_name_compliance,
title: "Client application includes `subject_name` if known",
description: %(
I attest that the client application includes the `subject_name` parameter if it is known for human or non-human requestors.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :subject_name_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

input :subject_id_compliance,
title: "Client application includes `subject_id` for human requestors when `subject_name` is present",
description: %(
I attest that the client application includes the `subject_id` parameter for human requestors when the `subject_name` parameter is present.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :subject_id_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

input :subject_id_npi_compliance,
title: "Client application uses NPI for `subject_id` in US Realm human requestors",
description: %(
I attest that the client application uses the National Provider Identifier (NPI) as the value for `subject_id` for human requestors in the US Realm.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :subject_id_npi_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

input :consent_reference_compliance,
title: "Client application ensures `consent_reference` URLs are resolvable",
description: %(
I attest that the client application ensures that the `consent_reference` parameter includes URLs that are resolvable by the receiving party and omits `consent_reference` if `consent_policy` is not present.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :consent_reference_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert subject_name_compliance == 'true',
'Client application did not include `subject_name` when it was known.'
pass subject_name_compliance_note if subject_name_compliance_note.present?

assert subject_id_compliance == 'true',
'Client application did not include `subject_id` for human requestors when `subject_name` was present.'
pass subject_id_compliance_note if subject_id_compliance_note.present?

assert subject_id_npi_compliance == 'true',
'Client application did not use NPI for `subject_id` for human requestors in the US Realm.'
pass subject_id_npi_compliance_note if subject_id_npi_compliance_note.present?

assert consent_reference_compliance == 'true',
'Client application did not ensure `consent_reference` URLs were resolvable or omitted `consent_reference` when `consent_policy` was not present.'
pass consent_reference_compliance_note if consent_reference_compliance_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
module UDAPSecurityTestKit
class ClientSecurityAndCSRFProtectionAttestationTest < Inferno::Test
title 'Client Security and CSRF Protection Compliance'
id :udap_security_client_security_csrf_protection
description %(
Client applications SHALL comply with the requirements for Client Security and CSRF Protection:
- Implement CSRF protection for its redirection URI.
- Use a binding value for CSRF protection that contains a non-guessable value.
- Ensure the user-agent's authenticated state is accessible only to the client and user-agent, protected by the same-origin policy.
)
verifies_requirements 'hl7.fhir.us.udap-security@275',
'hl7.fhir.us.udap-security@276',
'hl7.fhir.us.udap-security@277'

input :csrf_protection_implementation,
title: "Client application implements CSRF protection for its redirection URI",
description: %(
I attest that the client application implements CSRF protection for its redirection URI to prevent cross-site request forgery attacks.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :csrf_protection_implementation_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

input :csrf_binding_value_compliance,
title: "Client application uses a non-guessable binding value for CSRF protection",
description: %(
I attest that the client application uses a binding value for CSRF protection that contains a non-guessable value to ensure security.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :csrf_binding_value_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

input :authenticated_state_protection,
title: "Client application ensures authenticated state is protected by same-origin policy",
description: %(
I attest that the client application ensures the user-agent's authenticated state is stored in a location accessible only to the client and user-agent, protected by the same-origin policy.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :authenticated_state_protection_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert csrf_protection_implementation == 'true',
'Client application did not implement CSRF protection for its redirection URI.'
pass csrf_protection_implementation_note if csrf_protection_implementation_note.present?

assert csrf_binding_value_compliance == 'true',
'Client application did not use a non-guessable binding value for CSRF protection.'
pass csrf_binding_value_compliance_note if csrf_binding_value_compliance_note.present?

assert authenticated_state_protection == 'true',
'Client application did not ensure the user-agent\'s authenticated state is protected by the same-origin policy.'
pass authenticated_state_protection_note if authenticated_state_protection_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module UDAPSecurityTestKit
class IdPSupportsRequiredScopesAttestationTest < Inferno::Test
title 'IdP supports required scopes'
id :udap_security_idp_supports_scopes
description %(
Identity Providers (IdPs) SHALL include `"openid"` and `"udap"` in the array of scopes returned for the `scopes_supported` parameter.
)
verifies_requirements 'hl7.fhir.us.udap-security@235'

input :idp_supports_required_scopes,
title: "IdP supports required scopes",
description: %(
I attest that the Identity Provider (IdP) includes `"openid"` and `"udap"` in the array of scopes returned for the `scopes_supported` parameter.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :idp_supports_required_scopes_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert idp_supports_required_scopes == 'true',
'Identity Provider (IdP) did not demonstrate support for required scopes.'
pass idp_supports_required_scopes_note if idp_supports_required_scopes_note.present?
end
end
end
Loading
Loading