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.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module UDAPSecurityTestKit
class B2BAuthorizationExtensionObjectAttestationTest < Inferno::Test
title 'Complies with requirements for the B2B Flow and Authorization Extension Object'
id :udap_security_b2b_authorization_extension_object
description %(
Client application complies with requirements for the B2B Flow and Authorization Extension Object and:
- Includes `subject_name` parameter if it is known for human or non-human requestors.
- Includes `subject_id` parameter for human requestors when the `subject_name` parameter is present.
- Uses the National Provider Identifier (NPI) as the value for `subject_id` for human requestors in the US Realm.
- Ensures that the `consent_reference` parameter includes URLs that are resolvable by the receiving party.
- Omits `consent_reference` if `consent_policy` is not present.
- Ensures that the Requestor’s User, if applicable, is using the app only as authorized by the Requestor.
- Omits the `extensions` claim for client apps using the `authorization_code` flow.
- Includes the `subject_role` value if known for human requestors when the `subject_name` parameter is
present, and for US Realm, uses values/formats constrained by trust communities (preferably from the
NUCC Provider Taxonomy Code Set).
- Includes the `organization_id` value, using a URI scheme defined by the trust community.
)
verifies_requirements 'hl7.fhir.us.udap-security_1.0.0@187',
'hl7.fhir.us.udap-security_1.0.0@199',
'hl7.fhir.us.udap-security_1.0.0@203',
'hl7.fhir.us.udap-security_1.0.0@204',
'hl7.fhir.us.udap-security_1.0.0@205',
'hl7.fhir.us.udap-security_1.0.0@206',
'hl7.fhir.us.udap-security_1.0.0@207',
'hl7.fhir.us.udap-security_1.0.0@208',
'hl7.fhir.us.udap-security_1.0.0@213',
'hl7.fhir.us.udap-security_1.0.0@219',
'hl7.fhir.us.udap-security_1.0.0@220',
'hl7.fhir.us.udap-security_1.0.0@221'

input :b2b_authorization_extension_object_compliance,
title: 'Complies with requirements for the B2B Flow and Authorization Extension Object',
description: %(
I attest that the client application complies with requirements for the B2B Flow and Authorization
Extension Object and:
- Includes `subject_name` parameter if it is known for human or non-human requestors.
- Includes `subject_id` parameter for human requestors when the `subject_name` parameter is present.
- Uses the National Provider Identifier (NPI) as the value for `subject_id` for human requestors in the
US Realm.
- Ensures that the `consent_reference` parameter includes URLs that are resolvable by the receiving party.
- Omits `consent_reference` if `consent_policy` is not present.
- Ensures that the Requestor’s User, if applicable, is using the app only as authorized by the Requestor.
- Omits the `extensions` claim for client apps using the `authorization_code` flow.
- Includes the `subject_role` value if known for human requestors when the `subject_name` parameter is
present, and for US Realm, uses values/formats constrained by trust communities (preferably from the
NUCC Provider Taxonomy Code Set).
- Includes the `organization_id` value, using a URI scheme defined by the trust community.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :b2b_authorization_extension_object_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert b2b_authorization_extension_object_compliance == 'true',
'Client application did not comply with requirements for the B2B Authorization Extension Object.'
if b2b_authorization_extension_object_compliance_note.present?
pass b2b_authorization_extension_object_compliance_note
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module UDAPSecurityTestKit
class ClientAuthorizationCodeUsageAttestationTest < Inferno::Test
title 'Uses authorization code correctly'
id :udap_security_client_auth_code_usage
description %(
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](https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1)
of RFC 6749.
)
verifies_requirements 'hl7.fhir.us.udap-security_1.0.0@136',
'hl7.fhir.us.udap-security_1.0.0@188'

input :authorization_code_usage_correctly,
title: 'Uses authorization code 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](https://datatracker.ietf.org/doc/html/rfc6749#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,50 @@
module UDAPSecurityTestKit
class ClientSecurityAndCSRFProtectionAttestationTest < Inferno::Test
title 'Complies with Client Security and CSRF Protection'
id :udap_security_client_security_csrf_protection
description %(
Client applications complies with the requirements for Client Security and CSRF Protection:
- Implements CSRF protection for its redirection URI.
- Uses a binding value for CSRF protection that contains a non-guessable value.
- Ensures 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_1.0.0@275',
'hl7.fhir.us.udap-security_1.0.0@276',
'hl7.fhir.us.udap-security_1.0.0@277'

input :csrf_protection_implementation,
title: 'Complies with the requirements for Client Security and CSRF Protection',
description: %(
I attest that the client application complies with the requirements for Client Security and CSRF Protection:
- Implements CSRF protection for its redirection URI.
- Uses a binding value for CSRF protection that contains a non-guessable value.
- Ensures the user-agent's authenticated state is 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 :csrf_protection_implementation_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert csrf_protection_implementation == 'true',
'Client application did not comply with the requirements for Client Security and CSRF Protection.'
pass csrf_protection_implementation_note if csrf_protection_implementation_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module UDAPSecurityTestKit
class CryptographicAlgorithmsAndSecurityProtocolsAttestationTest < Inferno::Test
title 'supports the RS256 signature algorithm'
id :udap_security_crypto_algorithms_and_protocols
description %(
Client application supports the RS256 signature algorithm as defined in as defined in
[RFC 7518](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1) for UDAP workflows.
)
verifies_requirements 'hl7.fhir.us.udap-security_1.0.0@4'

input :crypto_algorithms_and_protocols_compliance,
title: 'Supports the RS256 signature algorithm',
description: %(
I attest that the client application supports the RS256 signature algorithm as defined in as defined in
[RFC 7518](https://datatracker.ietf.org/doc/html/rfc7518#section-3.1) for UDAP workflows.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}

input :crypto_algorithms_and_protocols_compliance_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert crypto_algorithms_and_protocols_compliance == 'true',
'Client application did not comply with cryptographic algorithms and security protocols requirements
(RS256 support).'
pass crypto_algorithms_and_protocols_compliance_note if crypto_algorithms_and_protocols_compliance_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module UDAPSecurityTestKit
class DataHolderAuthRequestScopeAttestationTest < Inferno::Test
title 'Data Holder Authentication Request Contains `openid` and `udap` Scopes'
id :udap_security_data_holder_auth_request_scope
description %(
Data holder's authentication request to the Identity Provider includes both
`openid` and `udap` in the `scope` query parameter.
)
verifies_requirements 'hl7.fhir.us.udap-security_1.0.0@256'

input :auth_request_scope_contains_openid_udap,
title: 'Authentication request `scope` contains `openid` and `udap`',
description: %(
I attest that the data holder's authentication request to the Identity Provider includes both
`openid` and `udap` in the `scope` query parameter.
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :auth_request_scope_contains_openid_udap_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert auth_request_scope_contains_openid_udap == 'true',
'Authentication request did not include both `openid` and `udap` in the `scope` query parameter.'
pass auth_request_scope_contains_openid_udap_note if auth_request_scope_contains_openid_udap_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module UDAPSecurityTestKit
class IdPAuthenticationComplianceAttestationTest < Inferno::Test
title 'Identity Provider Authenticates User per OIDC Core and UDAP Tiered OAuth'
id :udap_security_idp_authentication_compliance
description %(
The Identity Provider authenticates the user according to
[Sections 3.1.2.2 - 3.1.2.6 of OIDC Core](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation)
and Sections 4.1 - 4.2 of [UDAP Tiered OAuth](https://www.udap.org/udap-user-auth-stu1.html).
)
verifies_requirements 'hl7.fhir.us.udap-security_1.0.0@257'

input :idp_authenticates_per_spec,
title: 'IdP authenticates user per OIDC Core and UDAP Tiered OAuth',
description: %(
I attest that the Identity Provider authenticates the user according to
[Sections 3.1.2.2 - 3.1.2.6 of OIDC Core](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequestValidation)
and Sections 4.1 - 4.2 of [UDAP Tiered OAuth](https://www.udap.org/udap-user-auth-stu1.html).
),
type: 'radio',
default: 'false',
options: {
list_options: [
{
label: 'Yes',
value: 'true'
},
{
label: 'No',
value: 'false'
}
]
}
input :idp_authenticates_per_spec_note,
title: 'Notes, if applicable:',
type: 'textarea',
optional: true

run do
assert idp_authenticates_per_spec == 'true',
'Identity Provider did not authenticate the user as per OIDC Core and UDAP Tiered OAuth specifications.'
pass idp_authenticates_per_spec_note if idp_authenticates_per_spec_note.present?
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module UDAPSecurityTestKit
class IdPSupportsRequiredScopesAttestationTest < Inferno::Test
title 'Supports required scopes in IdPs'
id :udap_security_idp_supports_scopes
description %(
Identity Provider (IdP) includes `"openid"` and `"udap"` in the array of scopes returned
for the `scopes_supported` parameter.
)
verifies_requirements 'hl7.fhir.us.udap-security_1.0.0@235'

input :idp_supports_required_scopes,
title: '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