feat: link local library

This commit is contained in:
gabdevele
2026-06-17 20:43:56 +02:00 Unverified
parent 9a770a2af0
commit db59882f33
327 changed files with 22274 additions and 1 deletions
@@ -0,0 +1,8 @@
from django.urls import reverse
def get_admin_change_view_url(obj: object) -> str:
return reverse(
"admin:{}_{}_change".format(obj._meta.app_label, type(obj).__name__.lower()),
args=(obj.pk,),
)
@@ -0,0 +1,9 @@
FA_METADATA = {
"contacts": ["[email protected]"],
"federation_fetch_endpoint": "https://registry.spid.agid.gov.it/oidc/fedapi/",
"federation_list_endpoint": "https://registry.spid.agid.gov.it/oidc/list/",
"federation_trust_mark_status_endpoint": "https://registry.spid.agid.gov.it/oidc/status/",
"federation_resolve_endpoint": "https://registry.spid.agid.gov.it/oidc/resolve/",
"homepage_uri": "https://spid.agid.gov.it/",
"organization_name": "Tal dei tali"
}
@@ -0,0 +1,33 @@
from copy import deepcopy
JWKS = {
"keys": [
{
"kty": "EC",
"kid": "sig-ec256-0",
"use": "sig",
"crv": "P-256",
"x": "2jM2df3IjB9VYQ0yz373-6EEot_1TBuTRaRYafMi5K0",
"y": "h6Zlz6XReK0L-iu4ZgxlozJEXgTGUFuuDl7o8b_8JnM",
},
{
"kty": "EC",
"kid": "enc-ec256-1",
"use": "enc",
"crv": "P-256",
"x": "QI31cvWP4GwnWIi-Z0IYHauQ4nPCk8Vf1BHoPazGqEc",
"y": "DBwf8t9-abpXGtTDlZ8njjxAb33kOMrOqiGsd9oRxr0",
},
]
}
JWKS_WITH_N_AND_EC_NO_CORRECT = deepcopy(JWKS)
JWKS_WITH_N_AND_EC_NO_CORRECT["keys"][0][
"n"
] = "iu4ZgxlozJEXgTGUFuuDl7o8b_8JnMswwddaQjhFkKk"
JWKS_WITH_X_AND_RSA_NO_CORRECT = deepcopy(JWKS)
JWKS_WITH_X_AND_RSA_NO_CORRECT["keys"][0][
"x"
] = "iu4ZgxlozJEXgTGUFuuDl7o8b_8JnMswwddaQjhFkKk"
JWKS_WITH_X_AND_RSA_NO_CORRECT["keys"][0]["kty"] = "RSA"
@@ -0,0 +1,91 @@
from copy import deepcopy
from spid_cie_oidc.entity.tests.jwks_settings import JWKS, JWKS_WITH_N_AND_EC_NO_CORRECT
OP_METADATA = {
"issuer": "https://idserver.servizicie.interno.gov.it/op/",
"authorization_endpoint": "https://idserver.servizicie.interno.gov.it/op/auth",
"token_endpoint": "https://idserver.servizicie.interno.gov.it/op/token",
"userinfo_endpoint": "https://idserver.servizicie.interno.gov.it/op/userinfo",
"introspection_endpoint": "https://idserver.servizicie.interno.gov.it/op/introspect",
"revocation_endpoint": "https://idserver.servizicie.interno.gov.it/op/revoke",
"jwks_uri": "https://idserver.servizicie.interno.gov.it/.well-known/jwks.json",
"subject_types_supported": ["pairwise"],
"token_endpoint_auth_signing_alg_values_supported" : ["ES256"],
"id_token_encryption_alg_values_supported": ["RSA-OAEP"],
"request_object_encryption_enc_values_supported": ["A256CBC-HS512"],
"token_endpoint_auth_methods_supported": ["private_key_jwt"],
"userinfo_encryption_alg_values_supported": ["RSA-OAEP"],
"id_token_encryption_enc_values_supported": ["A256CBC-HS512"],
"id_token_signing_alg_values_supported": ["ES256"],
"userinfo_signing_alg_values_supported": ["ES256"],
"request_object_encryption_alg_values_supported": ["RSA-OAEP"],
"request_object_signing_alg_values_supported": ["ES256"],
"userinfo_encryption_enc_values_supported": ["A256CBC-HS512"],
"request_parameter_supported": True,
"subject_types_supported": ["pairwise"],
"token_endpoint_auth_methods_supported": ["private_key_jwt"],
"op_name": "Agenzia per l’Italia Digitale",
"op_uri": "https://www.agid.gov.it",
"acr_values_supported":[
"https://www.spid.gov.it/SpidL1",
"https://www.spid.gov.it/SpidL2",
"https://www.spid.gov.it/SpidL3"
],
"organization_name": "Tal dei tali"
}
OP_METADATA_CIE = deepcopy(OP_METADATA)
OP_METADATA_CIE["scopes_supported"] = ["openid", "offline_access", "email"]
OP_METADATA_CIE["response_types_supported"] = ["code"]
OP_METADATA_CIE["response_modes_supported"] = ["query", "form_post"]
OP_METADATA_CIE["grant_types_supported"] = ["authorization_code", "refresh_token"]
OP_METADATA_CIE["claims_supported"] = [
"given_name",
"family_name",
"email",
"email_verified",
"gender",
"birthdate",
"phone_number",
"phone_number_verified",
"place_of_birth",
"address",
"document_details",
"https://attributes.eid.gov.it/e_delivery_service",
"https://attributes.eid.gov.it/fiscal_number",
"https://attributes.eid.gov.it/idANPR",
"https://attributes.eid.gov.it/physical_phone_number",
]
OP_METADATA_CIE["claims_parameter_supported"] = True
OP_METADATA_CIE["tls_client_certificate_bound_access_tokens"] = True
OP_METADATA_CIE["authorization_response_iss_parameter_supported"] = True
OP_METADATA_CIE["userinfo_signing_alg_values_supported"] = ["ES256"]
OP_METADATA_CIE_JWKS_AND_JWKS_URI = deepcopy(OP_METADATA_CIE)
OP_METADATA_CIE_JWKS_AND_JWKS_URI["jwks"] = JWKS
OP_METADATA_CIE_JWKS_URI_NO_CORRECT = deepcopy(OP_METADATA_CIE)
OP_METADATA_CIE_JWKS_URI_NO_CORRECT[
"jwks_uri"
] = "https://registry.cie.gov.it/.well-known/"
OP_METADATA_SPID = deepcopy(OP_METADATA)
OP_METADATA_SPID["op_name"] = "Agenzia per l’Italia Digitale"
OP_METADATA_SPID["op_uri"] = "https://www.agid.gov.it"
OP_METADATA_SPID["userinfo_signing_alg_values_supported"] = ["RS384"]
OP_METADATA_SPID["acr_values_supported"] = [
"https://www.spid.gov.it/SpidL1",
"https://www.spid.gov.it/SpidL2",
"https://www.spid.gov.it/SpidL3",
]
OP_METADATA_SPID_JWKS_AND_JWKS_URI = deepcopy(OP_METADATA_SPID)
OP_METADATA_SPID_JWKS_AND_JWKS_URI["jwks"] = JWKS
OP_METADATA_SPID_JWKS_NO_JWKS_URI = deepcopy(OP_METADATA_SPID_JWKS_AND_JWKS_URI)
OP_METADATA_SPID_JWKS_NO_JWKS_URI.pop("jwks_uri")
OP_METADATA_SPID_JWKS_EC_NO_CORRECT = deepcopy(OP_METADATA_SPID_JWKS_NO_JWKS_URI)
OP_METADATA_SPID_JWKS_EC_NO_CORRECT["jwks"] = JWKS_WITH_N_AND_EC_NO_CORRECT
@@ -0,0 +1,97 @@
from copy import deepcopy
from spid_cie_oidc.entity.tests.jwks_settings import JWKS
RP_METADATA = {
"redirect_uris": [
"https://rp.example.it/spid/callback1/",
"https://rp.example.it/spid/callback2/",
],
"jwks_uri": "https://registry.cie.gov.it/keys.json",
"response_types": ["code"],
"grant_types": ["authorization_code", "refresh_token"],
"client_id": "https://rp.example.it/spid",
"client_name": "Nome RP",
"contacts": ["[email protected]"],
"subject_type": "pairwise",
"logo_uri": [
"https://rp.example.it/logo_small.jpg",
"https://rp.example.it/logo_big.jpg"
],
"scope" : ["openid", "offline_access", "profile"],
"organization_name": "Tal dei tali"
}
RP_METADATA_CIE = deepcopy(RP_METADATA)
RP_METADATA_CIE["tls_client_certificate_bound_access_tokens"] = True
RP_METADATA_CIE["application_type"] = "web"
RP_METADATA_SPID = deepcopy(RP_METADATA)
RP_METADATA_SPID_NO_REDIRECT_URIS = deepcopy(RP_METADATA_SPID)
RP_METADATA_SPID_NO_REDIRECT_URIS.pop("redirect_uris")
RP_METADATA_SPID_JWKS_AND_JWKS_URI = deepcopy(RP_METADATA_SPID)
RP_METADATA_SPID_JWKS_AND_JWKS_URI["jwks"] = JWKS
RP_METADATA_CIE_JWKS_AND_JWKS_URI = deepcopy(RP_METADATA_CIE)
RP_METADATA_CIE_JWKS_AND_JWKS_URI["jwks"] = JWKS
RP_METADATA_CIE_NO_REDIRECT_URIS = deepcopy(RP_METADATA_CIE)
RP_METADATA_CIE_NO_REDIRECT_URIS.pop("redirect_uris")
RP_METADATA_SPID_NOJWKS_NOJWKS_URI = deepcopy(RP_METADATA_SPID)
RP_METADATA_SPID_NOJWKS_NOJWKS_URI.pop("jwks_uri")
RP_METADATA_CIE_NOJWKS_NOJWKS_URI = deepcopy(RP_METADATA_CIE)
RP_METADATA_CIE_NOJWKS_NOJWKS_URI.pop("jwks_uri")
RP_METADATA_JWK1 = {'use': 'sig', 'kty': 'RSA', 'n': 'w8H80eT2zrs2XQ-SApZG9TkuXDuIxANfCVHt4fFqNnOEZaCNWqlTQIo0JiSBE-QmzZ09TYP1BJpESuQf_PUeLRVPfYHsBVk5OYvhT27_nYlV7_1LsFGLxxsIa-hswMMzvW-1_huKLy6Fp0WP0ouUJAHsF_eYVtO1ApRhvlIVd5azM4k7t8Lh8lkCSdF1SfGHfXnXJRb-XensZ0cFSfe2Koq9mD7jpGLXlPpXxj8Ow0g7KYT5kVtWE5ULmNmO7BIN1Hx4HpggbbEGgC9FyjKw4GfFb-csnB-icBPf_60HomjrkFFt6vTjrcqQaHOj-sEjP36N8rMSBiMmiMSPnsHhMQ', 'e': 'AQAB', 'd': 'jEDxjcTZXBbgBV8Bgt7-qfW1FJoHDEFKFxhfMpHQQoETa-jTPhCxOD2MzYM8A-9kKc8tu9r-crTAl1PI42kPnMd283phixd5G5Tv8gSaGdnq-45ka0iRuC7TItUdDiMNb_2YzB4ZLGLNmaIKQJSGqCHEcQuRVyxJtTZwrXaMMOhDqJaWUvUQWF5C7g5O5mOVTkNKw6ujzhqcWa4N3NE-HwcbVW_9st4s1c_ng-DlwLTptaeM5j-LOeZMX1zcVlwYMi5ZkYYY6FHHjYI4nBWDtqhvf-64QaTv8exIjk8PcxHOwhfLTWiHPLk14af7U_pCzkP87WQCBgNfvt3WILQ5DQ', 'p': '75eNHkWaYQMgzVfFwif5uftSxqOhFU6VkxNKdqoRuFxJuVTO-M-vbQc3BwPxms2xrpizU6zGcoPGPvccDi0G040wZh34pWDVABMgGMKXKmeTwj8FuM1DzOVq8DKHmdrhk1gaQbPAP8JVOVYK7uh_lG5wmz3X-En1McMk-E8g8Ic', 'q': '0Sny6DLNtDP1_B9qiyCaMtRqPSAUZ1ohCZRlBT6-IGRR31Kt5S2JcVNDnF5w4dunlDY4nhIBZ0v0VyzWKgDXj6qrFY1pm1iE29gW227YsVRWQU8xWGpBwEu8nxNMr0u0zfe0QEGWU4RvNAsZPRa31HU87Vm7I3NSZ34DZsCZJoc', 'kid': 'HIvo33-Km7n03ZqKDJfWVnlFudsW28YhQZx5eaXtAKA'}
RP_METADATA_JWK1_pub = {'use': 'sig', 'kty': 'RSA', 'n': 'w8H80eT2zrs2XQ-SApZG9TkuXDuIxANfCVHt4fFqNnOEZaCNWqlTQIo0JiSBE-QmzZ09TYP1BJpESuQf_PUeLRVPfYHsBVk5OYvhT27_nYlV7_1LsFGLxxsIa-hswMMzvW-1_huKLy6Fp0WP0ouUJAHsF_eYVtO1ApRhvlIVd5azM4k7t8Lh8lkCSdF1SfGHfXnXJRb-XensZ0cFSfe2Koq9mD7jpGLXlPpXxj8Ow0g7KYT5kVtWE5ULmNmO7BIN1Hx4HpggbbEGgC9FyjKw4GfFb-csnB-icBPf_60HomjrkFFt6vTjrcqQaHOj-sEjP36N8rMSBiMmiMSPnsHhMQ', 'e': 'AQAB', 'kid': 'HIvo33-Km7n03ZqKDJfWVnlFudsW28YhQZx5eaXtAKA'}
RP_METADATA_JWK2 = {'alg': 'RSA-OAEP', 'use': 'enc', 'kty': 'RSA', 'n': 'w8H80eT2zrs2XQ-SApZG9TkuXDuIxANfCVHt4fFqNnOEZaCNWqlTQIo0JiSBE-QmzZ09TYP1BJpESuQf_PUeLRVPfYHsBVk5OYvhT27_nYlV7_1LsFGLxxsIa-hswMMzvW-1_huKLy6Fp0WP0ouUJAHsF_eYVtO1ApRhvlIVd5azM4k7t8Lh8lkCSdF1SfGHfXnXJRb-XensZ0cFSfe2Koq9mD7jpGLXlPpXxj8Ow0g7KYT5kVtWE5ULmNmO7BIN1Hx4HpggbbEGgC9FyjKw4GfFb-csnB-icBPf_60HomjrkFFt6vTjrcqQaHOj-sEjP36N8rMSBiMmiMSPnsHhMQ', 'e': 'AQAB', 'd': 'jEDxjcTZXBbgBV8Bgt7-qfW1FJoHDEFKFxhfMpHQQoETa-jTPhCxOD2MzYM8A-9kKc8tu9r-crTAl1PI42kPnMd283phixd5G5Tv8gSaGdnq-45ka0iRuC7TItUdDiMNb_2YzB4ZLGLNmaIKQJSGqCHEcQuRVyxJtTZwrXaMMOhDqJaWUvUQWF5C7g5O5mOVTkNKw6ujzhqcWa4N3NE-HwcbVW_9st4s1c_ng-DlwLTptaeM5j-LOeZMX1zcVlwYMi5ZkYYY6FHHjYI4nBWDtqhvf-64QaTv8exIjk8PcxHOwhfLTWiHPLk14af7U_pCzkP87WQCBgNfvt3WILQ5DQ', 'p': '75eNHkWaYQMgzVfFwif5uftSxqOhFU6VkxNKdqoRuFxJuVTO-M-vbQc3BwPxms2xrpizU6zGcoPGPvccDi0G040wZh34pWDVABMgGMKXKmeTwj8FuM1DzOVq8DKHmdrhk1gaQbPAP8JVOVYK7uh_lG5wmz3X-En1McMk-E8g8Ic', 'q': '0Sny6DLNtDP1_B9qiyCaMtRqPSAUZ1ohCZRlBT6-IGRR31Kt5S2JcVNDnF5w4dunlDY4nhIBZ0v0VyzWKgDXj6qrFY1pm1iE29gW227YsVRWQU8xWGpBwEu8nxNMr0u0zfe0QEGWU4RvNAsZPRa31HU87Vm7I3NSZ34DZsCZJoc', 'kid': 'ENC-Km7n03ZqKDJfWVnlFudsW28YhQZx5eaXtAKA'}
RP_METADATA_JWK2_pub = {'alg': 'RSA-OAEP', 'use': 'enc', 'kty': 'RSA', 'n': 'w8H80eT2zrs2XQ-SApZG9TkuXDuIxANfCVHt4fFqNnOEZaCNWqlTQIo0JiSBE-QmzZ09TYP1BJpESuQf_PUeLRVPfYHsBVk5OYvhT27_nYlV7_1LsFGLxxsIa-hswMMzvW-1_huKLy6Fp0WP0ouUJAHsF_eYVtO1ApRhvlIVd5azM4k7t8Lh8lkCSdF1SfGHfXnXJRb-XensZ0cFSfe2Koq9mD7jpGLXlPpXxj8Ow0g7KYT5kVtWE5ULmNmO7BIN1Hx4HpggbbEGgC9FyjKw4GfFb-csnB-icBPf_60HomjrkFFt6vTjrcqQaHOj-sEjP36N8rMSBiMmiMSPnsHhMQ', 'e': 'AQAB', 'kid': 'ENC-Km7n03ZqKDJfWVnlFudsW28YhQZx5eaXtAKA'}
rp_onboarding_data = dict(
name="RP Test",
sub="http://rp-test.it/oidc/rp/",
type="openid_relying_party",
metadata_policy={"openid_relying_party": {"scope": {"value": ["openid"]}}},
is_active=True,
jwks = [RP_METADATA_JWK1_pub]
)
rp_conf = {
"sub": rp_onboarding_data["sub"],
"jwks_fed" : [RP_METADATA_JWK1],
"jwks_core" : [RP_METADATA_JWK1, RP_METADATA_JWK2],
"metadata": {
"openid_relying_party": {
"application_type": "web",
"client_registration_types": ["automatic"],
"client_name": "Name of this service called http://rp-test.it/oidc/rp/",
"contacts": ["[email protected]"],
"grant_types": ["refresh_token", "authorization_code"],
"redirect_uris": ["http://rp-test.it/oidc/rp/callback/"],
"response_types": ["code"],
"subject_type": "pairwise",
"client_id": "http://rp-test.it/oidc/rp/",
"jwks": {"keys": [RP_METADATA_JWK1_pub, RP_METADATA_JWK2_pub]},
}
},
"authority_hints": ["http://testserver/"],
"is_active": True,
}
RP_CONF_AS_JSON = {
"iss": rp_conf["sub"],
"sub": rp_conf["sub"],
"jwks": {
"keys": [RP_METADATA_JWK1_pub, RP_METADATA_JWK2_pub]
},
"metadata": rp_conf["metadata"],
"authority_hints":rp_conf["authority_hints"]
}
@@ -0,0 +1,44 @@
TA_SUB = "http://testserver/"
FA_METADATA = {
"federation_entity": {
"contacts": ["ops@localhost"],
"federation_fetch_endpoint": f"{TA_SUB}/fetch",
"federation_list_endpoint": f"{TA_SUB}/list/",
"homepage_uri": f"{TA_SUB}",
"name": "example TA",
}
}
TM_ISSUERS = {
"https://www.spid.gov.it/certification/rp/public": [
TA_SUB,
"https://public.intermediary.spid.it",
],
"https://www.spid.gov.it/certification/rp/private": [
TA_SUB,
"https://private.other.intermediary.it",
],
"https://sgd.aa.it/onboarding": ["https://sgd.aa.it"],
}
FA_CONSTRAINTS = {"max_path_length": 1}
ta_conf_data = dict(
sub=TA_SUB,
metadata=FA_METADATA,
constraints=FA_CONSTRAINTS,
is_active=1,
trust_mark_issuers=TM_ISSUERS,
)
TA_JWK_PRIVATE = {'kty': 'RSA', 'n': 'w8H80eT2zrs2XQ-SApZG9TkuXDuIxANfCVHt4fFqNnOEZaCNWqlTQIo0JiSBE-QmzZ09TYP1BJpESuQf_PUeLRVPfYHsBVk5OYvhT27_nYlV7_1LsFGLxxsIa-hswMMzvW-1_huKLy6Fp0WP0ouUJAHsF_eYVtO1ApRhvlIVd5azM4k7t8Lh8lkCSdF1SfGHfXnXJRb-XensZ0cFSfe2Koq9mD7jpGLXlPpXxj8Ow0g7KYT5kVtWE5ULmNmO7BIN1Hx4HpggbbEGgC9FyjKw4GfFb-csnB-icBPf_60HomjrkFFt6vTjrcqQaHOj-sEjP36N8rMSBiMmiMSPnsHhMQ', 'e': 'AQAB', 'd': 'jEDxjcTZXBbgBV8Bgt7-qfW1FJoHDEFKFxhfMpHQQoETa-jTPhCxOD2MzYM8A-9kKc8tu9r-crTAl1PI42kPnMd283phixd5G5Tv8gSaGdnq-45ka0iRuC7TItUdDiMNb_2YzB4ZLGLNmaIKQJSGqCHEcQuRVyxJtTZwrXaMMOhDqJaWUvUQWF5C7g5O5mOVTkNKw6ujzhqcWa4N3NE-HwcbVW_9st4s1c_ng-DlwLTptaeM5j-LOeZMX1zcVlwYMi5ZkYYY6FHHjYI4nBWDtqhvf-64QaTv8exIjk8PcxHOwhfLTWiHPLk14af7U_pCzkP87WQCBgNfvt3WILQ5DQ', 'p': '75eNHkWaYQMgzVfFwif5uftSxqOhFU6VkxNKdqoRuFxJuVTO-M-vbQc3BwPxms2xrpizU6zGcoPGPvccDi0G040wZh34pWDVABMgGMKXKmeTwj8FuM1DzOVq8DKHmdrhk1gaQbPAP8JVOVYK7uh_lG5wmz3X-En1McMk-E8g8Ic', 'q': '0Sny6DLNtDP1_B9qiyCaMtRqPSAUZ1ohCZRlBT6-IGRR31Kt5S2JcVNDnF5w4dunlDY4nhIBZ0v0VyzWKgDXj6qrFY1pm1iE29gW227YsVRWQU8xWGpBwEu8nxNMr0u0zfe0QEGWU4RvNAsZPRa31HU87Vm7I3NSZ34DZsCZJoc', 'kid': 'HIvo33-Km7n03ZqKDJfWVnlFudsW28YhQZx5eaXtAKA'}
TA_JWK_PUBLIC = {'kty': 'RSA', 'n': 'w8H80eT2zrs2XQ-SApZG9TkuXDuIxANfCVHt4fFqNnOEZaCNWqlTQIo0JiSBE-QmzZ09TYP1BJpESuQf_PUeLRVPfYHsBVk5OYvhT27_nYlV7_1LsFGLxxsIa-hswMMzvW-1_huKLy6Fp0WP0ouUJAHsF_eYVtO1ApRhvlIVd5azM4k7t8Lh8lkCSdF1SfGHfXnXJRb-XensZ0cFSfe2Koq9mD7jpGLXlPpXxj8Ow0g7KYT5kVtWE5ULmNmO7BIN1Hx4HpggbbEGgC9FyjKw4GfFb-csnB-icBPf_60HomjrkFFt6vTjrcqQaHOj-sEjP36N8rMSBiMmiMSPnsHhMQ', 'e': 'AQAB', 'kid': 'HIvo33-Km7n03ZqKDJfWVnlFudsW28YhQZx5eaXtAKA'}
ta_conf_data_as_json = dict(
sub=TA_SUB,
iss=TA_SUB,
metadata=FA_METADATA,
jwks ={
"keys": [TA_JWK_PUBLIC]
},
constraints=FA_CONSTRAINTS,
is_active=1,
trust_mark_issuers=TM_ISSUERS,
)
@@ -0,0 +1,55 @@
from django.contrib.auth import get_user_model
from django.test import TestCase, Client
from django.urls import reverse
from spid_cie_oidc.entity.models import *
from spid_cie_oidc.entity.jwtse import verify_jws
from . import get_admin_change_view_url
from .settings import *
class EntityConfigurationTest(TestCase):
def setUp(self):
self.ta_conf = FederationEntityConfiguration.objects.create(**ta_conf_data)
self.admin_user = get_user_model().objects.create_superuser(
username="superuser", password="secret", email="[email protected]"
)
def test_entity_configuration_admin(self):
c = Client()
c.login(username="superuser", password="secret")
# run test
response = c.get(get_admin_change_view_url(self.ta_conf))
self.assertEqual(response.status_code, 200)
def test_entity_configuration(self):
self.assertTrue(
isinstance(
FederationEntityConfiguration.get_active_conf(),
FederationEntityConfiguration,
)
)
self.assertTrue(isinstance(self.ta_conf, FederationEntityConfiguration))
self.assertFalse(self.ta_conf.is_leaf)
for i in (
"public_jwks",
"pems_as_json",
"kids",
"type",
"entity_configuration_as_jws",
):
attr = getattr(self.ta_conf, i)
self.assertTrue(attr)
md = self.ta_conf.entity_configuration_as_dict["metadata"]["federation_entity"]
for i in ("federation_fetch_endpoint",):
self.assertTrue(md.get(i))
# dulcis in fundo -> test the .well-knwon/openid-federation
wk_url = reverse("entity_configuration")
c = Client()
res = c.get(wk_url)
verify_jws(res.content.decode(), self.ta_conf.jwks_fed[0])
@@ -0,0 +1,37 @@
import logging
from django.test import TestCase
from pydantic import ValidationError
from spid_cie_oidc.entity.schemas.op_metadata import OPMetadataCie, OPMetadataSpid
from spid_cie_oidc.entity.tests.op_metadata_settings import (
OP_METADATA_CIE,
OP_METADATA_CIE_JWKS_AND_JWKS_URI,
OP_METADATA_SPID,
OP_METADATA_SPID_JWKS_AND_JWKS_URI,
OP_METADATA_SPID_JWKS_EC_NO_CORRECT,
OP_METADATA_SPID_JWKS_NO_JWKS_URI,
)
logger = logging.getLogger(__name__)
class OpMetadataTest(TestCase):
def test_op_metatada_cie(self):
OPMetadataCie(**OP_METADATA_CIE)
def test_op_metatada_cie_jwks_and_jwks_uri(self):
self.assertTrue(OPMetadataCie(**OP_METADATA_CIE_JWKS_AND_JWKS_URI))
def test_op_metatada_spid(self):
OPMetadataSpid(**OP_METADATA_SPID)
def test_op_metatada_spid_jwks_and_jwks_uri(self):
self.assertTrue(OPMetadataSpid(**OP_METADATA_SPID_JWKS_AND_JWKS_URI))
def test_op_metatada_spid_jwks_no_jwks_uri(self):
OPMetadataSpid(**OP_METADATA_SPID_JWKS_NO_JWKS_URI)
def test_op_metatada_spid_jws_ec_no_correct(self):
with self.assertRaises(ValidationError):
OPMetadataSpid(**OP_METADATA_SPID_JWKS_EC_NO_CORRECT)
@@ -0,0 +1,43 @@
from django.test import TestCase
from pydantic import ValidationError
from spid_cie_oidc.entity.schemas.rp_metadata import RPMetadataCie, RPMetadataSpid
from spid_cie_oidc.entity.tests.rp_metadata_settings import (
RP_METADATA_CIE,
RP_METADATA_SPID,
RP_METADATA_SPID_JWKS_AND_JWKS_URI,
RP_METADATA_SPID_NO_REDIRECT_URIS,
RP_METADATA_CIE_JWKS_AND_JWKS_URI,
RP_METADATA_CIE_NO_REDIRECT_URIS,
RP_METADATA_SPID_NOJWKS_NOJWKS_URI,
RP_METADATA_CIE_NOJWKS_NOJWKS_URI
)
class RPMetadataTest(TestCase):
def test_rp_metadataCie(self):
RPMetadataCie(**RP_METADATA_CIE)
def test_rp_metadataSpid(self):
RPMetadataSpid(**RP_METADATA_SPID)
def test_rp_metadataSpid_no_redirect_uris(self):
with self.assertRaises(ValidationError):
RPMetadataSpid(**RP_METADATA_SPID_NO_REDIRECT_URIS)
def test_rp_metadataSpid_jwks_and_jwks_uri(self):
self.assertTrue(RPMetadataSpid(**RP_METADATA_SPID_JWKS_AND_JWKS_URI))
def test_rp_metadataSpid_no_jwks_and_no_jwks_uri(self):
with self.assertRaises(ValidationError):
RPMetadataSpid(**RP_METADATA_SPID_NOJWKS_NOJWKS_URI)
def test_rp_metadataCie_jwks_and_jwks_uri(self):
self.assertTrue(RPMetadataCie(**RP_METADATA_CIE_JWKS_AND_JWKS_URI))
def test_rp_metadataCie_no_redirect_uris(self):
with self.assertRaises(ValidationError):
RPMetadataCie(**RP_METADATA_CIE_NO_REDIRECT_URIS)
def test_rp_metadataCie_no_jwks_and_no_jwks_uri(self):
with self.assertRaises(ValidationError):
RPMetadataCie(**RP_METADATA_CIE_NOJWKS_NOJWKS_URI)
@@ -0,0 +1,24 @@
from django.test import TestCase
from pydantic import ValidationError
from spid_cie_oidc.entity.schemas.jwks import JwksCie, JwksSpid
from spid_cie_oidc.entity.tests.jwks_settings import (
JWKS,
JWKS_WITH_N_AND_EC_NO_CORRECT,
JWKS_WITH_X_AND_RSA_NO_CORRECT,
)
class JwksTest(TestCase):
def test_jwks_spid(self):
JwksSpid(**JWKS)
def test_jwks_cie(self):
JwksCie(**JWKS)
def test_jwks_with_n_and_ec_no_correct(self):
with self.assertRaises(ValidationError):
JwksSpid(**JWKS_WITH_N_AND_EC_NO_CORRECT)
def test_jwks_with_e_and_rsa_no_correct(self):
with self.assertRaises(ValidationError):
JwksCie(**JWKS_WITH_X_AND_RSA_NO_CORRECT)
@@ -0,0 +1,8 @@
from django.test import TestCase
from spid_cie_oidc.entity.schemas.fa_metadata import FAMetadata
from spid_cie_oidc.entity.tests.fa_metadata_settings import FA_METADATA
class FAMetadatTest(TestCase):
def test_fa_metadata(self):
FAMetadata(**FA_METADATA)
@@ -0,0 +1,91 @@
from copy import deepcopy
from django.test import TestCase
from spid_cie_oidc.entity.policy import (
apply_policy,
diff2policy,
gather_policies,
PolicyError
)
from spid_cie_oidc.entity.tests.rp_metadata_settings import RP_METADATA
from spid_cie_oidc.authority.tests.settings import rp_onboarding_data
class PolicyTest(TestCase):
def setUp(self):
pass
def test_gather_polices(self):
combined_policy = gather_policies([{}], "openid_relying_party")
self.assertTrue(combined_policy == {})
def test_gather_polices_rp(self):
combined_policy = gather_policies([{},rp_onboarding_data], "openid_relying_party")
self.assertTrue(combined_policy == {'scope': {'value': ['openid']}})
def test_apply_policy(self):
fa_policy = {}
fa_policy["contacts"] = {"add": "[email protected]"}
combined_policy = apply_policy(deepcopy(RP_METADATA), fa_policy)
combined_contacts = combined_policy["contacts"]
self.assertTrue("[email protected]" in combined_contacts)
self.assertTrue("[email protected]" in combined_contacts)
def test_apply_policy_one_of(self):
fa_policy = {}
fa_policy["logo_uri"] = {"one_of": ["logo1", "logo2"]}
with self.assertRaises(PolicyError):
apply_policy(deepcopy(RP_METADATA), fa_policy)
def test_apply_policy_subset_of(self):
fa_policy = {}
fa_policy["scope"] = {"subset_of": ["openid", "offline_access"]}
combined_contacts = apply_policy(deepcopy(RP_METADATA), fa_policy)
self.assertTrue('profile' not in combined_contacts["scope"])
def test_apply_policy_superset_of(self):
fa_policy = {}
fa_policy["scope"] = {"superset_of": ["openid"]}
RP_METADATA_LOCAL = deepcopy(RP_METADATA)
RP_METADATA_LOCAL["scope"] = ["offline_access"]
with self.assertRaises(PolicyError):
apply_policy(deepcopy(RP_METADATA_LOCAL), fa_policy)
def test_apply_policy_difference_value(self):
fa_policy = {}
fa_policy["client_id"] = {"value": "https://rp.example.it/spid"}
RP_METADATA_LOCAL = deepcopy(RP_METADATA)
RP_METADATA_LOCAL.pop("client_id")
combined_contacts = apply_policy(deepcopy(RP_METADATA_LOCAL), fa_policy)
self.assertTrue(combined_contacts["client_id"])
def test_apply_policy_difference_add(self):
fa_policy = {}
fa_policy["contacts"] = {"add": "[email protected]"}
RP_METADATA_LOCAL = deepcopy(RP_METADATA)
RP_METADATA_LOCAL.pop("contacts")
combined_contacts = apply_policy(deepcopy(RP_METADATA_LOCAL), fa_policy)
self.assertTrue(combined_contacts["contacts"])
self.assertTrue("[email protected]" in combined_contacts["contacts"])
def test_apply_policy_add(self):
fa_policy = {}
fa_policy["contacts"] = {"add": "[email protected]"}
combined_contacts = apply_policy(deepcopy(RP_METADATA), fa_policy)
self.assertTrue("[email protected]" in combined_contacts["contacts"])
self.assertTrue("[email protected]" in combined_contacts["contacts"])
def test_diff_two_policy(self):
fa_policy_old = {}
fa_policy_new = deepcopy(fa_policy_old)
fa_policy_new["contacts"] = {"add": "[email protected]"}
result = diff2policy(fa_policy_new, fa_policy_old)
diff = {
"contacts": {
"add": {
"add": "[email protected]"
}
}
}
self.assertTrue(result == diff)
@@ -0,0 +1,12 @@
import asyncio
from django.test import TestCase
from spid_cie_oidc.entity.http_client import http_get
class HttpClient(TestCase):
def test_http_client(self):
url = "https://icanhazip.com/"
get = http_get([url], {})
value = asyncio.run(get)
self.assertFalse(len(value) == 0)
@@ -0,0 +1,96 @@
import json
from unittest.mock import patch
from django.contrib.auth import get_user_model
from django.test import (
Client,
RequestFactory,
TestCase,
override_settings
)
from django.urls import reverse
from spid_cie_oidc.entity.tests.rp_metadata_settings import rp_conf
from spid_cie_oidc.entity.views import resolve_entity_statement
from spid_cie_oidc.entity.models import (
FederationEntityConfiguration,
FetchedEntityStatement,
TrustChain,
StaffToken
)
from spid_cie_oidc.entity.tests.settings import ta_conf_data
from spid_cie_oidc.entity.utils import (
datetime_from_timestamp,
exp_from_now,
iat_now
)
def create_tc():
TA_FES = FetchedEntityStatement.objects.create(
sub="http://testserver/",
iss="http://testserver/",
exp=datetime_from_timestamp(exp_from_now(33)),
iat=datetime_from_timestamp(iat_now()),
)
return TrustChain.objects.create(
sub="http://rp-test.it/oidc/rp/",
exp=datetime_from_timestamp(exp_from_now(33)),
jwks = [],
metadata=[],
status="valid",
trust_anchor=TA_FES,
is_active=True,
)
class ResolveEntityStatementTest(TestCase):
def setUp(self):
self.factory = RequestFactory()
self.user = get_user_model().objects.create(
username="test",
first_name="test",
last_name="test",
email="[email protected]",
is_staff = True
)
self.user.set_password("test")
self.user.save()
StaffToken.objects.create(
user = self.user,
token = "secret-token",
is_active = True
)
self.ta_conf = FederationEntityConfiguration.objects.create(**ta_conf_data)
self.sub_conf = FederationEntityConfiguration.objects.create(**rp_conf)
self.ta_fes = FetchedEntityStatement.objects.create(
sub=ta_conf_data["sub"],
iss=ta_conf_data["sub"],
exp=datetime_from_timestamp(exp_from_now(33)),
iat=datetime_from_timestamp(iat_now()),
)
@override_settings(HTTP_CLIENT_SYNC=True)
def test_resolve_entity_statement(self):
client = Client()
url = reverse("oidcfed_resolve")
client.login(username="test", password="test")
data = {"sub" : rp_conf["sub"], "trust_anchor" : ta_conf_data["sub"]}
request = self.factory.get(url, data, **{'HTTP_AUTHORIZATION': "secret-token"})
self.patcher = patch(
"spid_cie_oidc.entity.trust_chain_operations.get_or_create_trust_chain",
return_value = create_tc()
)
self.patcher.start()
res = resolve_entity_statement(request, format='json')
self.patcher.stop()
_json = json.loads(res.content.decode())
self.assertTrue(_json.get("iss") == ta_conf_data["sub"])
self.assertTrue(_json.get("sub") == rp_conf["sub"])
self.assertTrue("trust_chain" in _json)
self.assertTrue("metadata" in _json)
@@ -0,0 +1,81 @@
from copy import deepcopy
from django.core.exceptions import ValidationError
from django.test import TestCase
from spid_cie_oidc.authority.tests.settings import (
RP_METADATA_JWK1,
RP_METADATA_JWK1_pub
)
from spid_cie_oidc.entity.tests.op_metadata_settings import OP_METADATA
from spid_cie_oidc.entity.tests.rp_metadata_settings import RP_METADATA_SPID
from spid_cie_oidc.entity.validators import (
validate_entity_metadata,
validate_metadata_algs,
validate_private_jwks,
validate_public_jwks
)
class ValidatrTest(TestCase):
def setUp(self):
pass
def test_validate_public_jwks_with_private_key(self):
with self.assertRaises(Exception):
validate_public_jwks(RP_METADATA_JWK1)
def test_validate_private_jwks_with_public_key(self):
with self.assertRaises(Exception):
validate_private_jwks(RP_METADATA_JWK1_pub)
def test_validate_public_jwks(self):
validate_public_jwks(RP_METADATA_JWK1_pub)
def test_validate_private_jwks(self):
validate_private_jwks(RP_METADATA_JWK1)
def test_validate_metadata_algs_ok(self):
op_md = {}
op_md["openid_provider"] = OP_METADATA
validate_metadata_algs(op_md)
def test_validate_metadata_algs_with_error(self):
OP_METADATA_NO_CORRECT = deepcopy(OP_METADATA)
OP_METADATA_NO_CORRECT["token_endpoint_auth_signing_alg_values_supported"] = ["ciao"]
op_md = {}
op_md["openid_provider"] = OP_METADATA_NO_CORRECT
with self.assertRaises(ValidationError):
validate_metadata_algs(op_md)
def test_validate_entity_op_metadata(self):
op_md = {}
op_md["openid_provider"] = deepcopy(OP_METADATA)
validate_entity_metadata(op_md)
def test_validate_entity_no_valid_op_metadata(self):
op_md = {}
op_md["openid_provider"] = deepcopy(OP_METADATA)
op_md["openid_provider"].pop("issuer")
with self.assertRaises(ValidationError):
validate_entity_metadata(op_md)
def test_validate_entity_rp_metadata(self):
rp_md = {}
rp_md["openid_relying_party"] = deepcopy(RP_METADATA_SPID)
validate_entity_metadata(rp_md)
def test_validate_entity_no_valid_rp_metadata(self):
rp_md = {}
rp_md["openid_relying_party"] = deepcopy(RP_METADATA_SPID)
rp_md["openid_relying_party"].pop("grant_types")
with self.assertRaises(ValidationError):
validate_entity_metadata(rp_md)
def test_validate_entity_no_entity_type(self):
rp_md = {}
rp_md = deepcopy(RP_METADATA_SPID)
with self.assertRaises(ValidationError):
validate_entity_metadata(rp_md)
@@ -0,0 +1,40 @@
from unittest.mock import patch
from django.test import TestCase, override_settings
from spid_cie_oidc.authority.models import FederationDescendant, FederationEntityAssignedProfile, FederationEntityProfile
from spid_cie_oidc.authority.tests.mocked_responses import EntityResponseNoIntermediate
from spid_cie_oidc.entity.models import FederationEntityConfiguration
from spid_cie_oidc.entity.tests.settings import ta_conf_data
from spid_cie_oidc.authority.tests.settings import (
rp_conf,
RP_PROFILE,
rp_onboarding_data
)
from spid_cie_oidc.entity.statements import TrustMark
class StatementTest(TestCase):
def setUp(self):
self.ta_conf = FederationEntityConfiguration.objects.create(**ta_conf_data)
self.rp_conf = FederationEntityConfiguration.objects.create(**rp_conf)
self.rp_profile = FederationEntityProfile.objects.create(**RP_PROFILE)
self.rp = FederationDescendant.objects.create(**rp_onboarding_data)
self.rp_assigned_profile = FederationEntityAssignedProfile.objects.create(
descendant=self.rp, profile=self.rp_profile, issuer=self.ta_conf
)
self.trust_mark = self.rp_assigned_profile.trust_mark_as_jws
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.get", return_value=EntityResponseNoIntermediate())
def test_validate_by_its_issuer(self, mocked):
self.tm = TrustMark(self.trust_mark)
TrustMark.validate_by_its_issuer(self.tm)
self.assertTrue(self.tm.is_valid)
@@ -0,0 +1,59 @@
from unittest.mock import patch
from django.test import TestCase
from spid_cie_oidc.authority.tests.settings import (
RP_CONF_AS_JSON,
RP_METADATA_JWK1,
rp_conf
)
from spid_cie_oidc.entity.exceptions import InvalidEntityConfiguration
from spid_cie_oidc.entity.jwtse import create_jws
from spid_cie_oidc.entity.tests.settings import (
TA_JWK_PRIVATE,
ta_conf_data,
ta_conf_data_as_json
)
from spid_cie_oidc.entity.trust_chain import TrustChainBuilder
from spid_cie_oidc.entity.utils import (
datetime_from_timestamp,
exp_from_now,
iat_now
)
EXP = datetime_from_timestamp(exp_from_now(33))
NOW = datetime_from_timestamp(iat_now())
def create_entity_config():
JWS_RP = create_jws(RP_CONF_AS_JSON, RP_METADATA_JWK1, typ="entity-statement+jwt")
JWS_TA = create_jws(ta_conf_data_as_json, TA_JWK_PRIVATE, typ="entity-statement+jwt")
return [JWS_RP, JWS_TA]
class TrustChainTest(TestCase):
def setUp(self):
self.tcb = TrustChainBuilder(
subject = rp_conf["sub"],
trust_anchor = ta_conf_data["sub"]
)
def test_get_trust_anchor_configuration(self):
self.patcher = patch(
"spid_cie_oidc.entity.trust_chain.get_entity_configurations",
return_value = create_entity_config()
)
self.patcher.start()
TrustChainBuilder.get_trust_anchor_configuration(self.tcb)
self.patcher.stop()
def test_get_subject_configuration_failed(self):
self.patcher = patch(
"spid_cie_oidc.entity.trust_chain.get_entity_configurations",
return_value = []
)
self.patcher.start()
with self.assertRaises(InvalidEntityConfiguration):
TrustChainBuilder.get_subject_configuration(self.tcb)
self.patcher.stop()
@@ -0,0 +1,21 @@
from django.test import TestCase
from spid_cie_oidc.entity.schemas.resolve_endpoint import ResolveRequest
from .rp_metadata_settings import rp_conf
TA_SUB = "http://testserver.it/"
RESOLVE_REQUEST = {
"sub": rp_conf["sub"],
"trust_anchor": TA_SUB,
"format": "json",
}
class SchemaTest(TestCase):
def setUp(self) -> None:
return super().setUp()
def test_resolve_request(self):
ResolveRequest(**RESOLVE_REQUEST)