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,212 @@
import json
import logging
from spid_cie_oidc.provider.tests.settings import op_conf, op_conf_priv_jwk
from spid_cie_oidc.authority.tests.settings import rp_conf, INTERMEDIARY_JWK1
from spid_cie_oidc.entity.jwtse import create_jws, create_jwe
from spid_cie_oidc.entity.utils import iat_now, exp_from_now, get_key, KeyUsage
from spid_cie_oidc.entity.utils import get_jwks
from cryptojwt.jws.utils import left_hash
logger = logging.getLogger(__name__)
class MockedTokenEndPointResponse:
def __init__(self):
self.status_code = 200
@property
def content(self):
id_token = {
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'nonce': 'ljbvL3rpscgS4ZGda7cgibXHr7vrNREW',
'at_hash': '',
'c_hash': 'tij0h-zL_bSrsVXy-d3qHw',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'iss': op_conf["sub"],
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
access_token = {
'iss': op_conf["sub"],
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'client_id': rp_conf["metadata"]["openid_relying_party"]["client_id"],
'scope': 'openid',
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
jwt_at = create_jws(access_token, op_conf_priv_jwk, typ="at+jwt")
id_token['at_hash'] = left_hash(jwt_at, "HS256")
jwt_id = create_jws(id_token, op_conf_priv_jwk)
self.access_token = jwt_at
self.id_token = jwt_id
res = {
"access_token": jwt_at,
"id_token": jwt_id,
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid",
}
return json.dumps(res).encode()
class MockedTokenEndPointNoCorrectResponse:
def __init__(self):
self.status_code = 200
@property
def content(self):
id_token = {
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'nonce': 'ljbvL3rpscgS4ZGda7cgibXHr7vrNREW',
'at_hash': '',
'c_hash': 'tij0h-zL_bSrsVXy-d3qHw',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'iss': op_conf["sub"],
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
access_token = {
'iss': op_conf["sub"],
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'client_id': rp_conf["metadata"]["openid_relying_party"]["client_id"],
'scope': 'openid',
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
jwt_at = create_jws(access_token, op_conf_priv_jwk, typ="at+jwt")
id_token['at_hash'] = left_hash(jwt_at, "HS256")
jwt_id = create_jws(id_token, op_conf_priv_jwk)
self.access_token = jwt_at
self.id_token = jwt_id
res = {
"access_token": jwt_at,
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid",
}
return json.dumps(res).encode()
class MockedTokenEndPointNoCorrectIdTokenResponse:
def __init__(self):
self.status_code = 200
@property
def content(self):
id_token = {
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'nonce': 'ljbvL3rpscgS4ZGda7cgibXHr7vrNREW',
'at_hash': '',
'c_hash': 'tij0h-zL_bSrsVXy-d3qHw',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'iss': op_conf["sub"],
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
access_token = {
'iss': op_conf["sub"],
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'client_id': rp_conf["metadata"]["openid_relying_party"]["client_id"],
'scope': 'openid',
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
jwt_at = create_jws(access_token, op_conf_priv_jwk, typ="at+jwt")
id_token['at_hash'] = left_hash(jwt_at, "HS256")
jwt_id = create_jws(id_token, INTERMEDIARY_JWK1)
self.access_token = jwt_at
self.id_token = jwt_id
res = {
"access_token": jwt_at,
"token_type": "Bearer",
"id_token": jwt_id,
"expires_in": 3600,
"scope": "openid",
}
return json.dumps(res).encode()
class MockedTokenEndPointNoCorrectAtHashResponse:
def __init__(self):
self.status_code = 200
@property
def content(self):
id_token = {
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'nonce': 'ljbvL3rpscgS4ZGda7cgibXHr7vrNREW',
'at_hash': '45e66ce53e48273dca5a446',
'c_hash': 'tij0h-zL_bSrsVXy-d3qHw',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'iss': op_conf["sub"],
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
access_token = {
'iss': op_conf["sub"],
'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b',
'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],],
'client_id': rp_conf["metadata"]["openid_relying_party"]["client_id"],
'scope': 'openid',
'jti': '402e61bd-950c-4934-83d4-c09a05468828',
'exp': exp_from_now(),
'iat': iat_now()
}
jwt_at = create_jws(access_token, op_conf_priv_jwk, typ="at+jwt")
jwt_id = create_jws(id_token, op_conf_priv_jwk)
self.access_token = jwt_at
self.id_token = jwt_id
res = {
"access_token": jwt_at,
"id_token": jwt_id,
"token_type": "Bearer",
"expires_in": 3600,
"scope": "openid",
}
return json.dumps(res).encode()
class MockedUserInfoResponse:
def __init__(self):
self.status_code = 200
@property
def content(self):
jwt = {
"sub": 'asdasdasdasasdasdas',
"https://attributes.eid.gov.it/fiscal_number": "sdfsfs908df09s8df90s8fd0"
}
jws = create_jws(jwt, op_conf_priv_jwk)
jwks = get_jwks(rp_conf["metadata"]["openid_relying_party"])
key = get_key(jwks, KeyUsage.encryption)
jwe = create_jwe(
jws,
key
)
return jwe.encode()
class MockedLogout:
@property
def content(self):
pass
@@ -0,0 +1,51 @@
from django.test import Client, TestCase
from django.urls import reverse
from spid_cie_oidc.relying_party.models import OidcAuthenticationToken
from spid_cie_oidc.relying_party.utils import html_json_preview
class OidcRpTest(TestCase):
# TODO: re enable
def _test_stupid_logout(self):
# a stupid logout that MUST fail
url = f'{reverse("spid_cie_rpinitiated_logout")}'
req = Client()
res = req.get(url)
self.assertTrue(res.status_code == 302)
# end stupid logout test
# TODO: re enable
def _test_session(self):
url = f'{reverse("spid_cie_rp_begin")}?issuer_id=op_test'
req = Client()
res = req.get(url)
self.assertTrue(res.status_code == 302)
authz_url = f'{reverse("op_test:spid_oidc_op_authz")}?{res.url.split("?")[1]}'
res = req.get(authz_url)
self.assertTrue(res.status_code == 302)
self.assertIn("code=", res.url)
url = f'{reverse("spid_cie_rp_callback")}?{res.url.split("?")[1]}'
res = req.get(url)
self.assertTrue(res.status_code == 302)
url = f'{reverse("spid_cie_rp_echo_attributes")}'
res = req.get(url)
self.assertIn("sando", res.content.decode())
# test models
tokens = OidcAuthenticationToken.objects.first()
tokens.access_token_preview
tokens.id_token_preview
# and now logout
url = f'{reverse("spid_cie_rpinitiated_logout")}'
res = req.get(url)
self.assertTrue(res.status_code == 302)
# TODO: re enable
def _test_html_json_preview(self):
html_json_preview('{"a" : 34, "b" : 78}')
@@ -0,0 +1,15 @@
from django.test import TestCase
class OidcRPCliTests(TestCase):
def setUp(self):
# create a FederationEntityConfiguration SP
pass
def test_fetch_openid_providers(self):
overrides = dict(OIDCFED_IDENTITY_PROVIDERS="", OIDCFED_REQUIRED_TRUST_MARKS="")
with self.settings(**overrides):
pass
# out = self.call_command('fetch_openid_providers', '--start')
# self.assertEqual(out.splitlines()[0], "test arbitrary command")
@@ -0,0 +1,198 @@
import urllib
from copy import deepcopy
from unittest.mock import patch
from django.http import HttpRequest
from django.test import Client, TestCase, override_settings
from django.urls import reverse
from spid_cie_oidc.authority.tests.settings import rp_conf
from spid_cie_oidc.entity.models import (
FederationEntityConfiguration,
FetchedEntityStatement,
TrustChain,
)
from spid_cie_oidc.entity.jwtse import unpad_jwt_payload
from spid_cie_oidc.entity.tests.settings import TA_SUB
from spid_cie_oidc.entity.utils import datetime_from_timestamp, exp_from_now, iat_now
from spid_cie_oidc.provider.tests.settings import op_conf
def create_tc():
NOW = datetime_from_timestamp(iat_now())
EXP = datetime_from_timestamp(exp_from_now(33))
ta_fes = FetchedEntityStatement.objects.create(
sub=TA_SUB,
iss=TA_SUB,
exp=EXP,
iat=NOW,
)
return TrustChain.objects.create(
sub=op_conf["sub"],
exp=EXP,
jwks = [],
status="valid",
trust_anchor=ta_fes,
is_active=True,
)
def create_tc_metadata_no_correct():
NOW = datetime_from_timestamp(iat_now())
EXP = datetime_from_timestamp(exp_from_now(33))
ta_fes = FetchedEntityStatement.objects.create(
sub=TA_SUB,
iss=TA_SUB,
exp=EXP,
iat=NOW,
)
local_op_conf = deepcopy(op_conf)
metadata = local_op_conf["metadata"]
metadata["openid_provider"]["jwks"] = {"keys": []}
return TrustChain.objects.create(
sub=op_conf["sub"],
exp=EXP,
status="valid",
jwks = [],
metadata=metadata,
trust_anchor=ta_fes,
is_active=True,
)
class RPBeginTest(TestCase):
def setUp(self):
self.req = HttpRequest()
NOW = datetime_from_timestamp(iat_now())
EXP = datetime_from_timestamp(exp_from_now(33))
self.rp_conf = FederationEntityConfiguration.objects.create(**rp_conf)
self.ta_fes = FetchedEntityStatement.objects.create(
sub=TA_SUB,
iss=TA_SUB,
exp=EXP,
iat=NOW,
)
metadata = deepcopy(op_conf["metadata"])
self.trust_chain = TrustChain.objects.create(
sub=op_conf["sub"],
exp=EXP,
jwks = [],
metadata=metadata,
status="valid",
trust_anchor=self.ta_fes,
is_active=True,
)
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_rp_begin(self):
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue(res.status_code == 302)
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
@patch("spid_cie_oidc.relying_party.views.rp_begin.SpidCieOidcRpBeginView.get_oidc_op", return_value=None)
def test_rp_begin_no_tc(self, mocked):
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue("request rejected" in res.content.decode())
def test_no_request(self):
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"request": {}})
self.assertTrue(res.status_code == 404)
self.assertTrue("request rejected" in res.content.decode())
self.assertTrue("Missing provider url" in res.content.decode())
# I changed the code to get a smarter solution
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_no_unallowed_tc(self):
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": "provider"})
self.assertTrue(res.status_code == 403)
self.assertTrue("request rejected" in res.content.decode())
# self.assertTrue("Unallowed Trust Anchor" in res.content.decode())
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_no_rp_entity_conf(self):
FederationEntityConfiguration.objects.all().delete()
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue(res.status_code == 404)
self.assertTrue("request rejected" in res.content.decode())
self.assertTrue("Missing configuration" in res.content.decode())
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_invalid_provider_metadata(self):
metadata = deepcopy(op_conf["metadata"])
metadata["openid_provider"].pop("jwks")
self.trust_chain.metadata = metadata
self.trust_chain.save()
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue(res.status_code == 404)
self.assertTrue("request rejected" in res.content.decode())
self.assertTrue("Invalid provider Metadata" in res.content.decode())
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_tc_no_active(self):
self.trust_chain.is_active = False
self.trust_chain.save()
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue(res.status_code == 404)
self.assertTrue("request rejected" in res.content.decode())
self.assertTrue("found but DISABLED at" in res.content.decode())
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_failed_to_get_jwks(self):
metadata = deepcopy(op_conf["metadata"])
metadata['openid_provider'].pop("jwks")
metadata["jwks_uri"] = "jwks_uri"
self.trust_chain.metadata = metadata
self.trust_chain.save()
client = Client()
url = reverse("spid_cie_rp_begin")
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue(res.status_code == 404)
self.assertTrue("request rejected" in res.content.decode())
def test_rp_begin_tc_no_metadata(self):
client = Client()
url = reverse("spid_cie_rp_begin")
self.patcher = patch(
"spid_cie_oidc.relying_party.views.rp_begin.SpidCieOidcRpBeginView.get_oidc_op",
return_value = create_tc()
)
self.patcher.start()
res = client.get(url, {"provider": op_conf["sub"], "trust_anchor": TA_SUB})
self.assertTrue("request rejected" in res.content.decode())
self.patcher.stop()
@override_settings(OIDCFED_DEFAULT_TRUST_ANCHOR=TA_SUB, OIDCFED_TRUST_ANCHORS=[TA_SUB])
def test_rp_begin_tc_no_redirect_uri(self):
red_url = "http://rp-test.it/oidc/rp/callback-test/"
FederationEntityConfiguration.objects.all().delete()
local_rp_conf = deepcopy(rp_conf)
local_rp_conf["metadata"]["openid_relying_party"]["redirect_uris"] = [red_url],
self.rp_conf = FederationEntityConfiguration.objects.create(**local_rp_conf)
client = Client()
url = reverse("spid_cie_rp_begin")
TrustChain.objects.all()
res = client.get(
url,
{
"provider": op_conf["sub"],
"trust_anchor": TA_SUB,
"redirect_uri": "http://rp-test.it/oidc/rp/callback"
}
)
req = urllib.parse.parse_qs(res.url)['request'][0]
req_data = unpad_jwt_payload(req)
self.assertTrue(red_url in req_data['redirect_uri'])
@@ -0,0 +1,181 @@
from copy import deepcopy
import json
from unittest.mock import patch
from django.contrib.auth import get_user_model
from django.test import Client, TestCase, override_settings
from django.urls import reverse
from spid_cie_oidc.accounts.models import User
from spid_cie_oidc.entity.models import FederationEntityConfiguration
from spid_cie_oidc.entity.utils import get_jwks
from spid_cie_oidc.relying_party.models import OidcAuthentication
from spid_cie_oidc.authority.tests.settings import rp_conf
from spid_cie_oidc.provider.tests.settings import op_conf
from spid_cie_oidc.provider.tests.authn_request_settings import AUTHN_REQUEST_SPID
from spid_cie_oidc.relying_party.tests.mocked_response import (
MockedTokenEndPointNoCorrectIdTokenResponse,
MockedTokenEndPointNoCorrectResponse,
MockedTokenEndPointResponse,
MockedTokenEndPointNoCorrectAtHashResponse,
MockedUserInfoResponse
)
STATE = "fyZiOL9Lf2CeKuNT2JzxiLRDink0uPcd"
CODE = "usDwMnEzJPpG5oaV8x3j&"
class RpCallBack(TestCase):
def setUp(self):
self.rp_jwk = {
'use': 'sig',
'kty': 'RSA',
'kid': '19xSsWuFOo5bFBUECA5G3V5GEhC0s7X8TTCEykdzsmo',
'e': 'AQAB',
'n': 'vfzFzFAv4e1IPfH6XMeB_L3f9sRZuaOtRsAs7s6ujGv6PwVMPsdELqd2NzrmKrLih3ZysJ6RoRe87rGZUZu2GbDtZhupCPb-1MuxB810svua9PwCrQK2wADM8q26colAiAOGSt912LUPC6MOYus44xd7TUDtQcsm-3VXWu4DA19NQXOaUh2TRal6GKXr7D8teod0fo736oHTObWoDZ0KdAGlwxI6IbQKpipgTD6lZ3l9L6WSmdLI9T-TyyNV9fW6rNqhnbySCEGkCM-Up6C2GQqLTq76kQNSMGasXrd3qH07KnTLBZsFy4JV4L-ws3zgaB4PLBOdfYAYe-xSp9-H_Q', 'd': 'MYc9FXduFCrko2l6yEcmhvoE8fLcJT4bRQ-CZzswW-EmWtmJt_AAwVzcv6c2K7l4vrHNUmf0NRfYJC3ed1ztiyMJsI3TckfZxSXY39za6HIZQnaUSAAmHkXXKAjMS2Gmlg69KrW4picFZhY7AOSrbuBHP6uGbpmEbxd3D3hvBqiU6cn_TAwbIhsJniTuSYYbvHd8z93QCKBfp_nDMltz6WG8YUXFiqtzRKv62Y4K2J_zjyd7-JKiWEBh5FUNuqZ2txEV3-q6bwoh3lSGA1qZtVgU61CwHqGQK3uxfEGPV68O48NVJNEe4YgNE806IfREgprTe3osGHd2S96s-t8oYQ',
'p': '9pwMs9MCfes5vYzXb8n1BqAL3LGdPp48jg7iKD4mZ6oLpeCbwNqtB7zN24OqrOnP2nREL2ugkSU2bBrsMy1hZ6k2DnN7cZkNgv4CZ_lO35Bc9CF9j1sCTxUnXQknympL8HVZoG2TdxUL0P09TgiBYz8SVH-uxFnlCuVZBLx35Lk',
'q': 'xTjFHi0QGPYSXGgbUN5cl9LOw7K2ifULDbEPiYSnbzd_oVneA-q6BmanMM5CLrj8qKJPy2Cuz3do-ZZPG_SN5AU_x23K9Vga3honcomo7G0cYKi9wGPBKzAMCRNRFHp3f3BAcp6HUJRn02Q_F_xDmXeC8JiPeATSBIDCXv41I2U'
}
data = deepcopy(AUTHN_REQUEST_SPID)
self.rp_config = deepcopy(rp_conf)
authz_entry = dict(
client_id=self.rp_config["metadata"]["openid_relying_party"]["client_id"],
provider_id=op_conf["sub"],
data=json.dumps(data),
state=STATE,
provider_configuration=op_conf["metadata"]["openid_provider"],
)
OidcAuthentication.objects.create(**authz_entry)
self.rp_config["sub"] = self.rp_config["metadata"]["openid_relying_party"]["client_id"]
FederationEntityConfiguration.objects.create(**self.rp_config)
rp_conf_saved = FederationEntityConfiguration.objects.all().first()
get_jwks(rp_conf_saved.metadata['openid_relying_party'])[0]["kid"] = rp_conf_saved.jwks_core[0]["kid"]
rp_conf_saved.save()
self.op_conf = FederationEntityConfiguration.objects.create(**op_conf)
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback(self, mocked, mocked_2):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
user = get_user_model().objects.first()
self.assertTrue(
user.attributes['fiscal_number'] == "sdfsfs908df09s8df90s8fd0"
)
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_mixups_attacks(self, mocked, mocked_2):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE, "iss": "WRONG"})
self.assertTrue(res.status_code == 400)
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("spid_cie_oidc.relying_party.views.rp_callback.process_user_attributes", return_value=None)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_no_rp_attr_map(self, mocked, mocked_2, mocked_3):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue(res.status_code == 403)
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("spid_cie_oidc.relying_party.views.rp_callback.process_user_attributes", return_value=None)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_incorret_request(self, mocked, mocked_2, mocked_3):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {})
self.assertTrue("error" in res.json())
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("spid_cie_oidc.relying_party.views.rp_callback.process_user_attributes", return_value=None)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("spid_cie_oidc.relying_party.views.rp_callback.SpidCieOidcRpCallbackView.get_userinfo", return_value=None)
def test_rp_callback_no_userinfo(self, mocked, mocked_2, mocked_3):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue(res.status_code == 400)
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("spid_cie_oidc.relying_party.views.rp_callback.process_user_attributes", return_value=None)
@patch("spid_cie_oidc.relying_party.views.rp_callback.SpidCieOidcRpCallbackView.access_token_request", return_value=None)
def test_rp_callback_no_token_response(self, mocked, mocked_2):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue(res.status_code == 400)
self.assertTrue("invalid token response" in res.content.decode())
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_no_rp_conf(self, mocked, mocked_2):
FederationEntityConfiguration.objects.filter(
sub = self.rp_config["sub"]
).delete()
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue("Relying party not found" in res.content.decode())
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_no_authz(self, mocked, mocked_2):
OidcAuthentication.objects.all().delete()
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue("Authentication not found" in res.content.decode())
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_reunification(self, mocked, mocked_2):
user = User.objects.create(username = "username", attributes = {"fiscal_number" : "sdfsfs908df09s8df90s8fd0"}),
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
user = get_user_model().objects.first()
self.assertTrue(
user.attributes['fiscal_number'] == "sdfsfs908df09s8df90s8fd0"
)
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointNoCorrectResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_no_correct_token_response(self, mocked, mocked1):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue(res.status_code == 400)
self.assertTrue("invalid_request" in res.content.decode())
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointNoCorrectIdTokenResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_no_correct_id_token_response(self, mocked, mocked1):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue(res.status_code == 403)
self.assertTrue("invalid_token" in res.content.decode())
@override_settings(HTTP_CLIENT_SYNC=True)
@patch("requests.post", return_value=MockedTokenEndPointNoCorrectAtHashResponse())
@patch("requests.get", return_value=MockedUserInfoResponse())
def test_rp_callback_no_correct_at_hash_response(self, mocked, mocked1):
client = Client()
url = reverse("spid_cie_rp_callback")
res = client.get(url, {"state": STATE, "code": CODE})
self.assertTrue(res.status_code == 403)
self.assertTrue("at_hash verification failed" in res.content.decode())
@@ -0,0 +1,77 @@
from copy import deepcopy
from unittest.mock import patch
from django.contrib.auth import get_user_model
from django.test import Client, TestCase
from django.urls import reverse
from spid_cie_oidc.authority.tests.settings import rp_conf
from spid_cie_oidc.entity.models import FederationEntityConfiguration
from spid_cie_oidc.provider.tests.settings import op_conf
from spid_cie_oidc.relying_party.models import (
OidcAuthentication,
OidcAuthenticationToken
)
from spid_cie_oidc.relying_party.tests.mocked_response import MockedLogout
class RpIntiatedLogoutTest(TestCase):
def setUp(self):
self.user = get_user_model().objects.create(
username="test",
first_name="test",
last_name="test",
email="[email protected]",
)
self.user.set_password("test")
self.user.save()
authz_request = OidcAuthentication.objects.create(
client_id=rp_conf["metadata"]["openid_relying_party"]["client_id"],
provider_configuration=op_conf["metadata"]["openid_provider"],
)
self.authz_token = OidcAuthenticationToken.objects.create(
user= self.user,
authz_request = authz_request,
)
FederationEntityConfiguration.objects.create(**rp_conf)
self.admin_user = get_user_model().objects.create_superuser(
username="superuser", password="secret", email="[email protected]"
)
@patch("requests.post", return_value=MockedLogout())
def test_rpinitiated_logout(self, mokced):
c = Client()
c.login(username="test", password="test")
url = reverse("spid_cie_rpinitiated_logout")
res = c.get(url)
self.assertTrue(res.status_code == 302)
self.assertTrue(res.url == "/oidc/rp/landing")
def test_rpinitiated_logout_no_revocation_endpoint(self):
OidcAuthentication.objects.all().delete()
op_conf_local = deepcopy(op_conf["metadata"]["openid_provider"])
op_conf_local.pop("revocation_endpoint")
authz_request = OidcAuthentication.objects.create(
client_id=rp_conf["metadata"]["openid_relying_party"]["client_id"],
provider_configuration=op_conf_local,
)
self.authz_token = OidcAuthenticationToken.objects.create(
user= self.user,
authz_request = authz_request,
)
c = Client()
c.login(username="test", password="test")
url = reverse("spid_cie_rpinitiated_logout")
res = c.get(url)
self.assertTrue(res.status_code == 302)
self.assertTrue(res.url == "/oidc/rp/landing")
def test_rpinitiated_logout_no_auth_token(self):
OidcAuthenticationToken.objects.all().delete()
c = Client()
c.login(username="test", password="test")
url = reverse("spid_cie_rpinitiated_logout")
res = c.get(url)
self.assertTrue(res.status_code == 302)
self.assertTrue(res.url == "/oidc/rp/landing")
@@ -0,0 +1,65 @@
from unittest.mock import patch
from django.core.management import call_command
from django.test import TestCase, override_settings
from spid_cie_oidc.entity.models import FetchedEntityStatement, TrustChain
from spid_cie_oidc.entity.tests.settings import TA_SUB
from spid_cie_oidc.entity.utils import (
datetime_from_timestamp,
exp_from_now,
iat_now
)
from spid_cie_oidc.provider.tests.settings import op_conf
EXP = datetime_from_timestamp(exp_from_now(33))
NOW = datetime_from_timestamp(iat_now())
def create_tc():
ta_fes = FetchedEntityStatement.objects.create(
sub=TA_SUB,
iss=TA_SUB,
exp=EXP,
iat=NOW
)
return TrustChain.objects.create(
sub=op_conf["sub"],
exp=EXP,
jwks = [],
metadata=op_conf["metadata"],
status="valid",
trust_anchor=ta_fes,
is_active=True,
)
class FetchProviderTest(TestCase):
def setUp(self):
self.ta_fes = FetchedEntityStatement.objects.create(
sub=TA_SUB,
iss=TA_SUB,
exp=datetime_from_timestamp(exp_from_now(33)),
iat=datetime_from_timestamp(iat_now()),
)
def exec(self, cmd_name:str, *args, **kwargs):
call_command(
cmd_name,
*args,
**kwargs,
)
@override_settings(OIDCFED_IDENTITY_PROVIDERS = {"spid": {"http://127.0.0.1:8000/oidc/op/" :"http://testserver/"}, "cie":{}})
def test_fetch_provider(self):
self.patcher = patch(
"spid_cie_oidc.entity.trust_chain_operations.get_or_create_trust_chain",
return_value = create_tc()
)
self.patcher.start()
self.exec('fetch_openid_providers', '--start')
self.patcher.stop()
@@ -0,0 +1,40 @@
from django.test import Client, TestCase
from django.urls import reverse
from spid_cie_oidc.entity.models import FetchedEntityStatement, TrustChain
from spid_cie_oidc.entity.tests.settings import TA_SUB
from spid_cie_oidc.entity.utils import (
datetime_from_timestamp,
exp_from_now,
iat_now
)
from spid_cie_oidc.provider.tests.settings import op_conf
class RpLandingTest(TestCase):
def setUp(self) -> None:
NOW = datetime_from_timestamp(iat_now())
EXP = datetime_from_timestamp(exp_from_now(33))
self.ta_fes = FetchedEntityStatement.objects.create(
sub=TA_SUB,
iss=TA_SUB,
exp=EXP,
iat=NOW,
)
self.trust_chain = TrustChain.objects.create(
sub=op_conf["sub"],
exp=EXP,
jwks = [],
metadata=op_conf["metadata"],
status="valid",
trust_anchor=self.ta_fes,
is_active=True,
)
def test_rp_landing(self):
client = Client()
url = reverse("spid_cie_rp_landing")
res = client.get(url)
self.assertTrue(res.status_code == 200)
@@ -0,0 +1,18 @@
from django.test import Client, TestCase
from django.urls import reverse
class CallBackEchoAttributesTest(TestCase):
def setUp(self) -> None:
return super().setUp()
def test_call_back_echo_attributes(self):
client = Client()
url = reverse("spid_cie_rp_echo_attributes")
session = client.session
session.update({"oidc_rp_user_attrs": {"email":"[email protected]"}})
session.save()
res = client.get(url)
self.assertTrue(res.status_code == 200)
self.assertTrue("[email protected]" in res.content.decode())
@@ -0,0 +1,62 @@
import json
from django.contrib.auth import get_user_model
from django.test import TestCase
from spid_cie_oidc.authority.tests.settings import rp_conf
from spid_cie_oidc.entity.jwtse import create_jws
from spid_cie_oidc.provider.tests.settings import (
op_conf,
op_conf_priv_jwk
)
from spid_cie_oidc.relying_party.models import (
OidcAuthentication,
OidcAuthenticationToken
)
RP_SUB = rp_conf["sub"]
RP_CLIENT_ID = rp_conf["metadata"]["openid_relying_party"]["client_id"]
class RpModelTest(TestCase):
def setUp(self):
self.user = get_user_model().objects.create(
username="test",
first_name="test",
last_name="test",
email="[email protected]",
)
self.user.set_password("test")
self.user.save()
authz_request = OidcAuthentication.objects.create(
client_id=rp_conf["metadata"]["openid_relying_party"]["client_id"],
provider_configuration=op_conf["metadata"]["openid_provider"],
)
self.token = {
"iss": op_conf["sub"],
"sub": RP_SUB,
"aud": [RP_CLIENT_ID],
"client_id": RP_CLIENT_ID,
"scope": "openid",
}
self.rt_jws = create_jws(self.token, op_conf_priv_jwk)
self.authz_token = OidcAuthenticationToken.objects.create(
user= self.user,
authz_request = authz_request,
code = "code",
access_token = self.rt_jws,
id_token = self.rt_jws,
)
def test_token_preview(self):
result = OidcAuthenticationToken.token_preview(self.authz_token, self.rt_jws)
self.assertTrue(json.loads(result)["iss"] == "http://op-test/oidc/op/")
result = OidcAuthenticationToken.token_preview(self.authz_token, "")
self.assertTrue(result == "--")
result = OidcAuthenticationToken.token_preview(self.authz_token, "token")
self.assertTrue(result == None)
result = OidcAuthenticationToken.__str__(self.authz_token)
self.assertTrue("code" in result)
result = self.authz_token.access_token_preview
self.assertTrue(json.loads(result)["iss"] == "http://op-test/oidc/op/")
result = self.authz_token.id_token_preview
self.assertTrue(json.loads(result)["iss"] == "http://op-test/oidc/op/")