From c701ecbb3e2104d16c9ac3210f12cd1cc544bc52 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Thu, 20 Jul 2023 10:53:24 +0200 Subject: [PATCH 01/15] feat: different jti for every token type --- spid_cie_oidc/provider/views/__init__.py | 6 ++++-- spid_cie_oidc/relying_party/templates/echo_attributes.html | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/spid_cie_oidc/provider/views/__init__.py b/spid_cie_oidc/provider/views/__init__.py index 05bcdc05..76ec28ac 100644 --- a/spid_cie_oidc/provider/views/__init__.py +++ b/spid_cie_oidc/provider/views/__init__.py @@ -238,7 +238,6 @@ def validate_json_schema(self, payload, schema_type, error_description): def get_jwt_common_data(self): return { - "jti": str(uuid.uuid4()), "exp": exp_from_now(), "iat": iat_now() } @@ -253,6 +252,7 @@ def get_access_token( "aud": [authz.client_id], "client_id": authz.client_id, "scope": authz.authz_request["scope"], + "jti": str(uuid.uuid4()) } access_token.update(commons) @@ -293,7 +293,8 @@ def get_id_token( "c_hash": left_hash(authz.auth_code, "HS256"), "aud": [authz.client_id], "iss": iss_sub, - "acr": authz.acr + "acr": authz.acr, + "jti": str(uuid.uuid4()) } claims = self.get_id_token_claims(authz) if claims: @@ -324,6 +325,7 @@ def get_refresh_token( "c_hash": left_hash(authz.auth_code, "HS256"), "aud": authz.client_id, "iss": iss_sub, + "jti": str(uuid.uuid4()) } refresh_token.update(commons) return refresh_token diff --git a/spid_cie_oidc/relying_party/templates/echo_attributes.html b/spid_cie_oidc/relying_party/templates/echo_attributes.html index 01bd8091..e6e296dd 100644 --- a/spid_cie_oidc/relying_party/templates/echo_attributes.html +++ b/spid_cie_oidc/relying_party/templates/echo_attributes.html @@ -42,7 +42,7 @@

Log out - Verify Token (Introspection) + Verify Access Token (Introspection) {% if rt_expiration == 0 %} @@ -53,7 +53,7 @@

{% trans "Warning" %}:

{% else %}

ACCESS TOKEN

-

{% trans "The" %} access token {{ rt_jti }}
+

{% trans "The" %} access token {{ at_jti }}
{% trans "expires in" %} {{ at_expiration }}

From b973dabbdc1f7873337493066be21a7ac5bb98b5 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Thu, 20 Jul 2023 16:50:01 +0200 Subject: [PATCH 02/15] feat: refresh tokens renewal based on user consent timeframe validity with new settingslocal var OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME #seconds --- .../provider/settingslocal.py.example | 2 +- .../provider/views/token_endpoint.py | 102 ++++++++++-------- spid_cie_oidc/relying_party/views/__init__.py | 14 ++- .../relying_party/views/rp_extend_session.py | 4 +- .../views/rp_initiated_logout.py | 4 +- .../relying_party/views/rp_introspection.py | 4 +- 6 files changed, 75 insertions(+), 55 deletions(-) diff --git a/examples/provider/provider/settingslocal.py.example b/examples/provider/provider/settingslocal.py.example index d7a780d0..e4f446e1 100644 --- a/examples/provider/provider/settingslocal.py.example +++ b/examples/provider/provider/settingslocal.py.example @@ -19,7 +19,7 @@ ADMIN_PATH = 'admin/' OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000" OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR] OIDCFED_PROVIDER_PROFILE = "cie" - + OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600 #seconds OIDCFED_REQUIRED_TRUST_MARKS = [] #OIDCFED_FEDERATION_TRUST_MARKS_PROFILES = { diff --git a/spid_cie_oidc/provider/views/token_endpoint.py b/spid_cie_oidc/provider/views/token_endpoint.py index 9fe0a13b..6a878c7d 100644 --- a/spid_cie_oidc/provider/views/token_endpoint.py +++ b/spid_cie_oidc/provider/views/token_endpoint.py @@ -1,6 +1,6 @@ - import base64 import hashlib +import json import logging from djagger.decorators import schema @@ -23,30 +23,31 @@ OIDCFED_PROVIDER_PROFILES ) +from spid_cie_oidc.entity.utils import datetime_from_timestamp, exp_from_now, iat_now from . import OpBase -logger = logging.getLogger(__name__) +logger = logging.getLogger(__name__) schema_profile = OIDCFED_PROVIDER_PROFILES[OIDCFED_DEFAULT_PROVIDER_PROFILE] @schema( - methods=['GET','POST'], - post_request_schema = { + methods=['GET', 'POST'], + post_request_schema={ "authn_request": schema_profile["authorization_code"], "refresh_request": schema_profile["refresh_token"], }, - post_response_schema = { - "200": schema_profile["authorization_code_response"], - # TODO - # "200": schema_profile["refresh_token_response"], - "400": schema_profile["token_error_response"], + post_response_schema={ + "200": schema_profile["authorization_code_response"], + # TODO + # "200": schema_profile["refresh_token_response"], + "400": schema_profile["token_error_response"], }, - get_response_schema = { - "400": BaseModel + get_response_schema={ + "400": BaseModel }, - tags = ['Provider'] + tags=['Provider'] ) @method_decorator(csrf_exempt, name="dispatch") class TokenEndpoint(OpBase, View): @@ -77,20 +78,20 @@ def grant_auth_code(self, request, *args, **kwargs): # issued_token = IssuedToken.objects.filter( - session= self.authz, - revoked = False + session=self.authz, + revoked=False ).first() jwk_at = unpad_jwt_payload(issued_token.access_token) expires_in = self.get_expires_in(jwk_at['iat'], jwk_at['exp']) - iss_token_data = dict( # nosec B106 - access_token = issued_token.access_token, - id_token = issued_token.id_token, - token_type = "Bearer", # nosec B106 - expires_in = expires_in, + iss_token_data = dict( # nosec B106 + access_token=issued_token.access_token, + id_token=issued_token.id_token, + token_type="Bearer", # nosec B106 + expires_in=expires_in, # TODO: remove unsupported scope - scope = self.authz.authz_request["scope"], + scope=self.authz.authz_request["scope"], ) if issued_token.refresh_token: iss_token_data['refresh_token'] = issued_token.refresh_token @@ -98,14 +99,25 @@ def grant_auth_code(self, request, *args, **kwargs): def is_token_renewable(self, session) -> bool: issuedToken = IssuedToken.objects.filter( - session = session - ) - # TODO: check also ACR - return ( - (issuedToken.count() - 1) < getattr( - settings, "OIDCFED_PROVIDER_MAX_REFRESH", 1 - ) - ) + session=session + ).first() + + id_token = unpad_jwt_payload(issuedToken.id_token) + + consent_expiration = id_token['iat'] + getattr(settings, "OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME") + + delta = consent_expiration - iat_now() + + if delta > 0: + return True + return False + + # # TODO: check also ACR + # return ( + # (issuedToken.count() - 1) < getattr( + # settings, "OIDCFED_PROVIDER_MAX_REFRESH", 1 + # ) + # ) def grant_refresh_token(self, request, *args, **kwargs): """ @@ -119,8 +131,8 @@ def grant_refresh_token(self, request, *args, **kwargs): # 2. create a new instance of issuedtoken linked to the same sessions and revoke the older # 3. response with a new refresh, access and id_token issued_token = IssuedToken.objects.filter( - refresh_token = request.POST['refresh_token'], - revoked = False + refresh_token=request.POST['refresh_token'], + revoked=False ).first() if not issued_token: @@ -130,17 +142,17 @@ def grant_refresh_token(self, request, *args, **kwargs): "error_description": "Refresh token not found", }, - status = 400 + status=400 ) session = issued_token.session - if not self.is_token_renewable(session): # pragma: no cover + if not self.is_token_renewable(session): # pragma: no cover return JsonResponse( - { - "error": "invalid_request", - "error_description": "Refresh Token can no longer be updated", + { + "error": "invalid_request", + "error_description": "Refresh Token can no longer be updated", - }, status = 400 + }, status=400 ) iss_token_data = self.get_iss_token_data(session, self.get_issuer()) IssuedToken.objects.create(**iss_token_data) @@ -150,12 +162,12 @@ def grant_refresh_token(self, request, *args, **kwargs): jwk_at = unpad_jwt_payload(iss_token_data['access_token']) expires_in = self.get_expires_in(jwk_at['iat'], jwk_at['exp']) - data = dict( # nosec B106 - access_token = iss_token_data['access_token'], - id_token = iss_token_data['id_token'], - refresh_token = iss_token_data['refresh_token'], - token_type = "Bearer", # nosec B106 - expires_in = expires_in, + data = dict( # nosec B106 + access_token=iss_token_data['access_token'], + id_token=iss_token_data['id_token'], + refresh_token=iss_token_data['refresh_token'], + token_type="Bearer", # nosec B106 + expires_in=expires_in, ) return JsonResponse(data) @@ -174,7 +186,7 @@ def post(self, request, *args, **kwargs): "error": "invalid_request", "error_description": "Token request object validation failed", }, - status = 400 + status=400 ) self.commons = self.get_jwt_common_data() @@ -186,7 +198,7 @@ def post(self, request, *args, **kwargs): request.POST['client_id'], request.POST['client_assertion'] ) - except Exception as e: # pragma: no cover + except Exception as e: # pragma: no cover logger.warning( "Client authentication failed for " f"{request.POST.get('client_id', 'unknown')}: {e}" @@ -197,7 +209,7 @@ def post(self, request, *args, **kwargs): 'error': "unauthorized_client", 'error_description': "" - }, status = 403 + }, status=403 ) if request.POST.get("grant_type") == 'authorization_code': diff --git a/spid_cie_oidc/relying_party/views/__init__.py b/spid_cie_oidc/relying_party/views/__init__.py index 563b1d7c..c65836c8 100644 --- a/spid_cie_oidc/relying_party/views/__init__.py +++ b/spid_cie_oidc/relying_party/views/__init__.py @@ -9,6 +9,8 @@ from ..oidc import * from ..oauth2 import * +from enum import Enum + from spid_cie_oidc.entity.exceptions import InvalidTrustchain from spid_cie_oidc.entity.models import TrustChain from spid_cie_oidc.entity.trust_chain_operations import get_or_create_trust_chain @@ -21,6 +23,12 @@ logger = logging.getLogger(__name__) +class TokenRequestType(str, Enum): + refresh = "refresh" + revocation = "revocation" + introspection = "introspection" + + class SpidCieOidcRp: """ Baseclass with common methods for RPs @@ -110,16 +118,16 @@ def get_token_request(self, auth_token, request, token_type): client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer" ) - if token_type == 'refresh': # nosec - B105 + if token_type == TokenRequestType.refresh: #'refresh': # nosec - B105 token_request_data["grant_type"] = "refresh_token" token_request_data["refresh_token"] = auth_token.refresh_token audience = authz.provider_configuration["token_endpoint"] - elif token_type == 'revocation': # nosec - B105 + elif token_type == TokenRequestType.revocation: #'revocation': # nosec - B105 token_request_data["token"] = auth_token.access_token audience = authz.provider_configuration["revocation_endpoint"] - elif token_type == 'introspection': # nosec - B105 + elif token_type == TokenRequestType.introspection: #'introspection': # nosec - B105 token_request_data["token"] = auth_token.access_token audience = authz.provider_configuration["introspection_endpoint"] diff --git a/spid_cie_oidc/relying_party/views/rp_extend_session.py b/spid_cie_oidc/relying_party/views/rp_extend_session.py index f7d11ab4..f1e97b96 100644 --- a/spid_cie_oidc/relying_party/views/rp_extend_session.py +++ b/spid_cie_oidc/relying_party/views/rp_extend_session.py @@ -8,7 +8,7 @@ from ..oauth2 import * from ..oidc import * -from . import SpidCieOidcRp +from . import SpidCieOidcRp, TokenRequestType from django.views import View from spid_cie_oidc.entity.jwtse import ( @@ -49,7 +49,7 @@ def get(self, request, *args, **kwargs): auth_token = auth_tokens.last() try: - token_response = self.get_token_request(auth_token, request, "refresh") + token_response = self.get_token_request(auth_token, request, TokenRequestType.refresh) #"refresh") if token_response.status_code == 400: return HttpResponseRedirect(reverse("spid_cie_rp_landing")) diff --git a/spid_cie_oidc/relying_party/views/rp_initiated_logout.py b/spid_cie_oidc/relying_party/views/rp_initiated_logout.py index 0f51973d..80fe6239 100644 --- a/spid_cie_oidc/relying_party/views/rp_initiated_logout.py +++ b/spid_cie_oidc/relying_party/views/rp_initiated_logout.py @@ -9,7 +9,7 @@ from django.utils import timezone from ..models import OidcAuthenticationToken -from . import SpidCieOidcRp +from . import SpidCieOidcRp, TokenRequestType from django.views import View logger = logging.getLogger(__name__) @@ -47,7 +47,7 @@ def get(self, request): logout(request) try: - self.get_token_request(auth_token, request, "revocation") + self.get_token_request(auth_token, request, TokenRequestType.revocation) #"revocation") auth_token.logged_out = timezone.localtime() auth_token.save() except Exception as e: # pragma: no cover diff --git a/spid_cie_oidc/relying_party/views/rp_introspection.py b/spid_cie_oidc/relying_party/views/rp_introspection.py index b8842eeb..dbc0387a 100644 --- a/spid_cie_oidc/relying_party/views/rp_introspection.py +++ b/spid_cie_oidc/relying_party/views/rp_introspection.py @@ -7,7 +7,7 @@ from ..oauth2 import * from ..oidc import * -from . import SpidCieOidcRp +from . import SpidCieOidcRp, TokenRequestType from django.views import View @@ -48,7 +48,7 @@ def get(self, request, *args, **kwargs): auth_token = auth_tokens.last() try: - token_response = self.get_token_request(auth_token, request, "introspection") + token_response = self.get_token_request(auth_token, request, TokenRequestType.introspection) # "introspection") introspection_token_response = json.loads(token_response.content.decode()) data = {"introspection": introspection_token_response} return render(request, self.template, data) From a8d8b57c203d196220c5723a62f85732f63f90d1 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Thu, 20 Jul 2023 18:45:11 +0200 Subject: [PATCH 03/15] fix: refresh token tests with more complete tokenset and test RT emission outside OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME --- .../provider/tests/test_03_refresh_token.py | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/spid_cie_oidc/provider/tests/test_03_refresh_token.py b/spid_cie_oidc/provider/tests/test_03_refresh_token.py index 568cc761..ca9e6d78 100644 --- a/spid_cie_oidc/provider/tests/test_03_refresh_token.py +++ b/spid_cie_oidc/provider/tests/test_03_refresh_token.py @@ -1,5 +1,6 @@ from copy import deepcopy - +import time +from cryptojwt.jws.utils import left_hash from django.test import Client, TestCase, override_settings from django.urls import reverse from django.utils import timezone @@ -66,6 +67,31 @@ def setUp(self): "scope": "openid", } self.rt_jws = create_jws(refresh_token, op_conf_priv_jwk) + 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() + } + self.jwt_at = create_jws(access_token, op_conf_priv_jwk, typ="at+jwt") + id_token['at_hash'] = left_hash(self.jwt_at, "HS256") + self.jwt_id = create_jws(id_token, op_conf_priv_jwk) + session = OidcSession.objects.create( user=User.objects.create(username="username"), user_uid="", @@ -77,6 +103,8 @@ def setUp(self): ) IssuedToken.objects.create( refresh_token=self.rt_jws, + id_token=self.jwt_id, + access_token=self.jwt_at, session=session, expires=timezone.localtime() ) @@ -97,7 +125,7 @@ def test_grant_refresh_token(self): self.assertEqual(refresh_token["aud"], RP_CLIENT_ID) self.assertEqual(refresh_token["iss"], self.op_local_conf["sub"]) - @override_settings(OIDCFED_PROVIDER_MAX_REFRESH=1) + @override_settings(OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME=1) def test_grant_refresh_token_two_times(self): client = Client() url = reverse("oidc_provider_token_endpoint") @@ -117,5 +145,6 @@ def test_grant_refresh_token_two_times(self): refresh_token=res.json()["refresh_token"], grant_type="refresh_token" ) + time.sleep(1) res = client.post(url, request) self.assertTrue(res.status_code == 400) From 9dfc4dd4c22fb5a96e6f54cd5775d8787dec032e Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Fri, 21 Jul 2023 07:26:55 +0200 Subject: [PATCH 04/15] chore: changed RT renewal method description in webpage --- spid_cie_oidc/relying_party/templates/echo_attributes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spid_cie_oidc/relying_party/templates/echo_attributes.html b/spid_cie_oidc/relying_party/templates/echo_attributes.html index e6e296dd..0a1aa693 100644 --- a/spid_cie_oidc/relying_party/templates/echo_attributes.html +++ b/spid_cie_oidc/relying_party/templates/echo_attributes.html @@ -62,7 +62,7 @@

REFRESH TOKEN {{ rt_jti }}
{% trans "expires in" %} {{ rt_expiration }}

{% endif %} From cb71dbf924c5343760412022ac6174ef4a85cec6 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Fri, 21 Jul 2023 07:26:55 +0200 Subject: [PATCH 05/15] chore: changed RT renewal method description in webpage --- spid_cie_oidc/relying_party/templates/echo_attributes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spid_cie_oidc/relying_party/templates/echo_attributes.html b/spid_cie_oidc/relying_party/templates/echo_attributes.html index e6e296dd..ed0d00a2 100644 --- a/spid_cie_oidc/relying_party/templates/echo_attributes.html +++ b/spid_cie_oidc/relying_party/templates/echo_attributes.html @@ -62,7 +62,7 @@

REFRESH TOKEN {{ rt_jti }}
{% trans "expires in" %} {{ rt_expiration }}

{% endif %} From 24256032d9e1e755116fba57822c24a5d81ebb3c Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Fri, 21 Jul 2023 07:30:18 +0200 Subject: [PATCH 06/15] chore: changed RT renewal method description in webpage --- spid_cie_oidc/relying_party/templates/echo_attributes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spid_cie_oidc/relying_party/templates/echo_attributes.html b/spid_cie_oidc/relying_party/templates/echo_attributes.html index ed0d00a2..6a07ee36 100644 --- a/spid_cie_oidc/relying_party/templates/echo_attributes.html +++ b/spid_cie_oidc/relying_party/templates/echo_attributes.html @@ -62,7 +62,7 @@

REFRESH TOKEN {{ rt_jti }}
{% trans "expires in" %} {{ rt_expiration }}

{% endif %} From ba47d5fdb7654cf59dbf86297b700843a90be1a8 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Fri, 21 Jul 2023 09:32:33 +0200 Subject: [PATCH 07/15] chore: linting --- spid_cie_oidc/entity/jwtse.py | 4 ++-- spid_cie_oidc/entity/settings.py | 4 ++-- spid_cie_oidc/entity/validators.py | 2 +- spid_cie_oidc/entity/x509.py | 2 -- spid_cie_oidc/onboarding/views.py | 2 +- spid_cie_oidc/provider/settings.py | 6 ++++-- spid_cie_oidc/provider/views/token_endpoint.py | 3 +-- spid_cie_oidc/relying_party/views/__init__.py | 8 ++++---- spid_cie_oidc/relying_party/views/rp_begin.py | 3 ++- spid_cie_oidc/relying_party/views/rp_extend_session.py | 5 +---- spid_cie_oidc/relying_party/views/rp_initiated_logout.py | 2 +- spid_cie_oidc/relying_party/views/rp_introspection.py | 6 +----- 12 files changed, 20 insertions(+), 27 deletions(-) diff --git a/spid_cie_oidc/entity/jwtse.py b/spid_cie_oidc/entity/jwtse.py index 95714d8e..f5d40818 100644 --- a/spid_cie_oidc/entity/jwtse.py +++ b/spid_cie_oidc/entity/jwtse.py @@ -50,12 +50,12 @@ def create_jwe(plain_dict: Union[dict, str, int, None], jwk_dict: dict, **kwargs if isinstance(plain_dict, dict): _payload = json.dumps(plain_dict).encode() elif not plain_dict: - logger.warning(f"create_jwe with null payload!") + logger.warning("create_jwe with null payload!") _payload = "" elif isinstance(plain_dict, (str, int)): _payload = plain_dict else: - logger.error(f"create_jwe with unsupported payload type!") + logger.error("create_jwe with unsupported payload type!") _payload = "" _keyobj = JWE_CLASS( diff --git a/spid_cie_oidc/entity/settings.py b/spid_cie_oidc/entity/settings.py index 5bf1379c..b0704168 100644 --- a/spid_cie_oidc/entity/settings.py +++ b/spid_cie_oidc/entity/settings.py @@ -74,8 +74,8 @@ FEDERATION_DEFAULT_EXP = getattr(settings, "FEDERATION_DEFAULT_EXP", 2880) ENTITY_TYPE_LEAFS = [ - "openid_relying_party", - "openid_provider", + "openid_relying_party", + "openid_provider", "oauth_resource", "wallet_provider", "wallet_relying_party" diff --git a/spid_cie_oidc/entity/validators.py b/spid_cie_oidc/entity/validators.py index 26b00c0c..fc80c357 100644 --- a/spid_cie_oidc/entity/validators.py +++ b/spid_cie_oidc/entity/validators.py @@ -88,7 +88,7 @@ def validate_entity_metadata(value): raise ValidationError( f"RP metadata fail {e}. " ) - + # TODO - add wallet_provider and wallet_relying_party once standardized diff --git a/spid_cie_oidc/entity/x509.py b/spid_cie_oidc/entity/x509.py index 725d50ba..9282c961 100644 --- a/spid_cie_oidc/entity/x509.py +++ b/spid_cie_oidc/entity/x509.py @@ -1,5 +1,3 @@ -import datetime -import os from cryptography import x509 from cryptography.x509.oid import NameOID diff --git a/spid_cie_oidc/onboarding/views.py b/spid_cie_oidc/onboarding/views.py index d8f7872b..e5e0565e 100644 --- a/spid_cie_oidc/onboarding/views.py +++ b/spid_cie_oidc/onboarding/views.py @@ -286,7 +286,7 @@ def onboarding_decode_jwt(request): if not form_dict.get('jwk'): messages.error( request, - f"JWE needs a private jwk to be decrypted" + "JWE needs a private jwk to be decrypted" ) return render( request, "onboarding_decode_jwt.html", context, status = 400 diff --git a/spid_cie_oidc/provider/settings.py b/spid_cie_oidc/provider/settings.py index df842fdb..39fd4411 100644 --- a/spid_cie_oidc/provider/settings.py +++ b/spid_cie_oidc/provider/settings.py @@ -11,9 +11,11 @@ AuthenticationRequestDoc, AuthenticationRequestSpid ) -from spid_cie_oidc.provider.schemas.authn_response import AuthenticationErrorResponse, AuthenticationErrorResponseCie, AuthenticationResponse, AuthenticationResponseCie +from spid_cie_oidc.provider.schemas.authn_response import AuthenticationErrorResponse, AuthenticationErrorResponseCie, \ + AuthenticationResponse, AuthenticationResponseCie from spid_cie_oidc.provider.schemas.introspection_request import IntrospectionRequest -from spid_cie_oidc.provider.schemas.introspection_response import IntrospectionErrorResponseCie, IntrospectionErrorResponseSpid, IntrospectionResponse +from spid_cie_oidc.provider.schemas.introspection_response import IntrospectionErrorResponseCie, \ + IntrospectionErrorResponseSpid, IntrospectionResponse from spid_cie_oidc.provider.schemas.revocation_request import RevocationRequest from spid_cie_oidc.provider.schemas.revocation_response import RevocationErrorResponse from spid_cie_oidc.provider.schemas.token_requests import TokenAuthnCodeRequest, TokenRefreshRequest diff --git a/spid_cie_oidc/provider/views/token_endpoint.py b/spid_cie_oidc/provider/views/token_endpoint.py index 6a878c7d..aec455da 100644 --- a/spid_cie_oidc/provider/views/token_endpoint.py +++ b/spid_cie_oidc/provider/views/token_endpoint.py @@ -1,6 +1,5 @@ import base64 import hashlib -import json import logging from djagger.decorators import schema @@ -23,7 +22,7 @@ OIDCFED_PROVIDER_PROFILES ) -from spid_cie_oidc.entity.utils import datetime_from_timestamp, exp_from_now, iat_now +from spid_cie_oidc.entity.utils import iat_now from . import OpBase logger = logging.getLogger(__name__) diff --git a/spid_cie_oidc/relying_party/views/__init__.py b/spid_cie_oidc/relying_party/views/__init__.py index c65836c8..572d78d3 100644 --- a/spid_cie_oidc/relying_party/views/__init__.py +++ b/spid_cie_oidc/relying_party/views/__init__.py @@ -47,7 +47,7 @@ def get_oidc_op(self, request) -> TrustChain: ) trust_anchor = request.GET.get("trust_anchor", None) - if trust_anchor != None and trust_anchor not in settings.OIDCFED_TRUST_ANCHORS: + if trust_anchor is not None and trust_anchor not in settings.OIDCFED_TRUST_ANCHORS: logger.warning("Unallowed Trust Anchor") raise InvalidTrustchain("Unallowed Trust Anchor") @@ -118,16 +118,16 @@ def get_token_request(self, auth_token, request, token_type): client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer" ) - if token_type == TokenRequestType.refresh: #'refresh': # nosec - B105 + if token_type == TokenRequestType.refresh: token_request_data["grant_type"] = "refresh_token" token_request_data["refresh_token"] = auth_token.refresh_token audience = authz.provider_configuration["token_endpoint"] - elif token_type == TokenRequestType.revocation: #'revocation': # nosec - B105 + elif token_type == TokenRequestType.revocation: token_request_data["token"] = auth_token.access_token audience = authz.provider_configuration["revocation_endpoint"] - elif token_type == TokenRequestType.introspection: #'introspection': # nosec - B105 + elif token_type == TokenRequestType.introspection: token_request_data["token"] = auth_token.access_token audience = authz.provider_configuration["introspection_endpoint"] diff --git a/spid_cie_oidc/relying_party/views/rp_begin.py b/spid_cie_oidc/relying_party/views/rp_begin.py index 8273ef3d..86eb5608 100644 --- a/spid_cie_oidc/relying_party/views/rp_begin.py +++ b/spid_cie_oidc/relying_party/views/rp_begin.py @@ -14,7 +14,8 @@ from spid_cie_oidc.entity.jwtse import create_jws from spid_cie_oidc.entity.utils import get_jwks from spid_cie_oidc.entity.models import FederationEntityConfiguration -from spid_cie_oidc.relying_party.settings import OIDCFED_ACR_PROFILES, RP_PROVIDER_PROFILES, RP_DEFAULT_PROVIDER_PROFILES +from spid_cie_oidc.relying_party.settings import OIDCFED_ACR_PROFILES, RP_PROVIDER_PROFILES, \ + RP_DEFAULT_PROVIDER_PROFILES from ..models import OidcAuthentication from ..settings import ( diff --git a/spid_cie_oidc/relying_party/views/rp_extend_session.py b/spid_cie_oidc/relying_party/views/rp_extend_session.py index f1e97b96..85c86dc5 100644 --- a/spid_cie_oidc/relying_party/views/rp_extend_session.py +++ b/spid_cie_oidc/relying_party/views/rp_extend_session.py @@ -38,9 +38,6 @@ def get(self, request, *args, **kwargs): user=request.user ).filter(revoked__isnull=True) - default_logout_url = getattr( - settings, "LOGOUT_REDIRECT_URL", None - ) or reverse("spid_cie_rp_landing") if not auth_tokens: logger.warning( "Token request failed: not found any authentication session" @@ -49,7 +46,7 @@ def get(self, request, *args, **kwargs): auth_token = auth_tokens.last() try: - token_response = self.get_token_request(auth_token, request, TokenRequestType.refresh) #"refresh") + token_response = self.get_token_request(auth_token, request, TokenRequestType.refresh) # "refresh") if token_response.status_code == 400: return HttpResponseRedirect(reverse("spid_cie_rp_landing")) diff --git a/spid_cie_oidc/relying_party/views/rp_initiated_logout.py b/spid_cie_oidc/relying_party/views/rp_initiated_logout.py index 80fe6239..c91237fe 100644 --- a/spid_cie_oidc/relying_party/views/rp_initiated_logout.py +++ b/spid_cie_oidc/relying_party/views/rp_initiated_logout.py @@ -47,7 +47,7 @@ def get(self, request): logout(request) try: - self.get_token_request(auth_token, request, TokenRequestType.revocation) #"revocation") + self.get_token_request(auth_token, request, TokenRequestType.revocation) # "revocation") auth_token.logged_out = timezone.localtime() auth_token.save() except Exception as e: # pragma: no cover diff --git a/spid_cie_oidc/relying_party/views/rp_introspection.py b/spid_cie_oidc/relying_party/views/rp_introspection.py index dbc0387a..2b83424d 100644 --- a/spid_cie_oidc/relying_party/views/rp_introspection.py +++ b/spid_cie_oidc/relying_party/views/rp_introspection.py @@ -1,7 +1,6 @@ import logging from djagger.decorators import schema -from django.urls import reverse from ..models import OidcAuthenticationToken from ..oauth2 import * @@ -37,9 +36,6 @@ def get(self, request, *args, **kwargs): user=request.user ).filter(revoked__isnull=True) - default_logout_url = getattr( - settings, "LOGOUT_REDIRECT_URL", None - ) or reverse("spid_cie_rp_landing") if not auth_tokens: logger.warning( "Token request failed: not found any authentication session" @@ -48,7 +44,7 @@ def get(self, request, *args, **kwargs): auth_token = auth_tokens.last() try: - token_response = self.get_token_request(auth_token, request, TokenRequestType.introspection) # "introspection") + token_response = self.get_token_request(auth_token, request, TokenRequestType.introspection) introspection_token_response = json.loads(token_response.content.decode()) data = {"introspection": introspection_token_response} return render(request, self.template, data) From cf3c4bb01225c0ff0b45f4586e5dfdbf700b1010 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Fri, 21 Jul 2023 15:49:25 +0200 Subject: [PATCH 08/15] fix: error in user_attributes --- spid_cie_oidc/relying_party/templates/echo_attributes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spid_cie_oidc/relying_party/templates/echo_attributes.html b/spid_cie_oidc/relying_party/templates/echo_attributes.html index 6a07ee36..2b25f83f 100644 --- a/spid_cie_oidc/relying_party/templates/echo_attributes.html +++ b/spid_cie_oidc/relying_party/templates/echo_attributes.html @@ -62,7 +62,7 @@

REFRESH TOKEN {{ rt_jti }}
{% trans "expires in" %} {{ rt_expiration }}

{% endif %} From 79e654727fa565411d7f53ace492a7bafda62a23 Mon Sep 17 00:00:00 2001 From: Glauco <37829079+rglauco@users.noreply.github.com> Date: Fri, 21 Jul 2023 17:22:30 +0200 Subject: [PATCH 09/15] fix: settingslocal.py.example --- examples/provider/provider/settingslocal.py.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/provider/provider/settingslocal.py.example b/examples/provider/provider/settingslocal.py.example index e4f446e1..389c53b5 100644 --- a/examples/provider/provider/settingslocal.py.example +++ b/examples/provider/provider/settingslocal.py.example @@ -19,7 +19,7 @@ ADMIN_PATH = 'admin/' OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000" OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR] OIDCFED_PROVIDER_PROFILE = "cie" - OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600 #seconds +OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600 #seconds OIDCFED_REQUIRED_TRUST_MARKS = [] #OIDCFED_FEDERATION_TRUST_MARKS_PROFILES = { From bc18b35353cef314c488d329c3b93023731dcd05 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Tue, 25 Jul 2023 21:15:11 +0200 Subject: [PATCH 10/15] feat: first attempt to differentiate CIE and SPID behaviour within RT request using OIDCFED_PROVIDER_PROFILE --- .../settingslocal.py.example | 4 ++ .../provider/settingslocal.py.example | 6 ++- .../provider/views/token_endpoint.py | 39 +++++++++++-------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/examples/federation_authority/federation_authority/settingslocal.py.example b/examples/federation_authority/federation_authority/settingslocal.py.example index c004bcb9..2e9b3e69 100644 --- a/examples/federation_authority/federation_authority/settingslocal.py.example +++ b/examples/federation_authority/federation_authority/settingslocal.py.example @@ -29,6 +29,10 @@ OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000" OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR] +OIDCFED_PROVIDER_PROFILE = "spid" +OIDCFED_PROVIDER_MAX_REFRESH = 10 #used in SPID +#OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600 #used in CIE (seconds) + # for RP only OIDCFED_IDENTITY_PROVIDERS = { "spid": { diff --git a/examples/provider/provider/settingslocal.py.example b/examples/provider/provider/settingslocal.py.example index e4f446e1..e58b4554 100644 --- a/examples/provider/provider/settingslocal.py.example +++ b/examples/provider/provider/settingslocal.py.example @@ -18,8 +18,10 @@ ADMIN_PATH = 'admin/' # required for onboarding checks and also for all the leafs OIDCFED_DEFAULT_TRUST_ANCHOR = "http://127.0.0.1:8000" OIDCFED_TRUST_ANCHORS = [OIDCFED_DEFAULT_TRUST_ANCHOR] -OIDCFED_PROVIDER_PROFILE = "cie" - OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600 #seconds +OIDCFED_PROVIDER_PROFILE = "spid" +#OIDCFED_PROVIDER_MAX_REFRESH = 10 #used in SPID +OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME = 3600 #used in CIE (seconds) + OIDCFED_REQUIRED_TRUST_MARKS = [] #OIDCFED_FEDERATION_TRUST_MARKS_PROFILES = { diff --git a/spid_cie_oidc/provider/views/token_endpoint.py b/spid_cie_oidc/provider/views/token_endpoint.py index aec455da..e5010588 100644 --- a/spid_cie_oidc/provider/views/token_endpoint.py +++ b/spid_cie_oidc/provider/views/token_endpoint.py @@ -19,7 +19,7 @@ from spid_cie_oidc.provider.models import IssuedToken, OidcSession from spid_cie_oidc.provider.settings import ( OIDCFED_DEFAULT_PROVIDER_PROFILE, - OIDCFED_PROVIDER_PROFILES + OIDCFED_PROVIDER_PROFILES, ) from spid_cie_oidc.entity.utils import iat_now @@ -97,26 +97,31 @@ def grant_auth_code(self, request, *args, **kwargs): return JsonResponse(iss_token_data) def is_token_renewable(self, session) -> bool: - issuedToken = IssuedToken.objects.filter( - session=session - ).first() - - id_token = unpad_jwt_payload(issuedToken.id_token) + logger.info(OIDCFED_DEFAULT_PROVIDER_PROFILE) + if OIDCFED_DEFAULT_PROVIDER_PROFILE == "cie": + issuedToken = IssuedToken.objects.filter( + session=session + ).first() - consent_expiration = id_token['iat'] + getattr(settings, "OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME") + id_token = unpad_jwt_payload(issuedToken.id_token) - delta = consent_expiration - iat_now() + consent_expiration = id_token['iat'] + getattr(settings, "OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME") - if delta > 0: - return True - return False + delta = consent_expiration - iat_now() - # # TODO: check also ACR - # return ( - # (issuedToken.count() - 1) < getattr( - # settings, "OIDCFED_PROVIDER_MAX_REFRESH", 1 - # ) - # ) + if delta > 0: + return True + return False + elif OIDCFED_DEFAULT_PROVIDER_PROFILE == "spid": + # TODO: check also ACR + issuedToken = IssuedToken.objects.filter( + session=session + ) + return ( + (issuedToken.count() - 1) < getattr( + settings, "OIDCFED_PROVIDER_MAX_REFRESH", 1 + ) + ) def grant_refresh_token(self, request, *args, **kwargs): """ From b59219d40016ea4f485c903685edc122da22f695 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Tue, 25 Jul 2023 22:13:55 +0200 Subject: [PATCH 11/15] fix: [RP] differentiate refresh token tests CIE/SPID --- .../provider/tests/test_03_refresh_token.py | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/spid_cie_oidc/provider/tests/test_03_refresh_token.py b/spid_cie_oidc/provider/tests/test_03_refresh_token.py index ca9e6d78..595351c2 100644 --- a/spid_cie_oidc/provider/tests/test_03_refresh_token.py +++ b/spid_cie_oidc/provider/tests/test_03_refresh_token.py @@ -109,7 +109,8 @@ def setUp(self): expires=timezone.localtime() ) - def test_grant_refresh_token(self): + @override_settings(OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME=1, OIDCFED_DEFAULT_PROVIDER_PROFILE="cie") + def test_grant_refresh_token_cie(self): client = Client() url = reverse("oidc_provider_token_endpoint") request = dict( @@ -125,8 +126,8 @@ def test_grant_refresh_token(self): self.assertEqual(refresh_token["aud"], RP_CLIENT_ID) self.assertEqual(refresh_token["iss"], self.op_local_conf["sub"]) - @override_settings(OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME=1) - def test_grant_refresh_token_two_times(self): + @override_settings(OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME=1, OIDCFED_PROVIDER_PROFILE="cie") + def test_grant_refresh_token_two_times_cie(self): client = Client() url = reverse("oidc_provider_token_endpoint") request = dict( @@ -148,3 +149,26 @@ def test_grant_refresh_token_two_times(self): time.sleep(1) res = client.post(url, request) self.assertTrue(res.status_code == 400) + + # @override_settings(OIDCFED_PROVIDER_MAX_REFRESH=1, OIDCFED_PROVIDER_PROFILE="spid") + # def test_grant_refresh_token_two_times_spid(self): + # client = Client() + # url = reverse("oidc_provider_token_endpoint") + # request = dict( + # client_id=RP_CLIENT_ID, + # client_assertion=self.ca_jws, + # client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + # refresh_token=self.rt_jws, + # grant_type="refresh_token" + # ) + # res = client.post(url, request) + # self.assertTrue(res.status_code == 200) + # request = dict( + # client_id=RP_CLIENT_ID, + # client_assertion=self.ca_jws, + # client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + # refresh_token=res.json()["refresh_token"], + # grant_type="refresh_token" + # ) + # res = client.post(url, request) + # self.assertTrue(res.status_code == 400) \ No newline at end of file From 55cb066b39535194f7ab20c80bcd5c4706306a57 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Wed, 26 Jul 2023 07:50:05 +0200 Subject: [PATCH 12/15] test: enhanced refresh token tests for SPID and CIE --- .../provider/tests/test_03_refresh_token.py | 73 ++++++++++++------- .../provider/views/token_endpoint.py | 6 +- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/spid_cie_oidc/provider/tests/test_03_refresh_token.py b/spid_cie_oidc/provider/tests/test_03_refresh_token.py index 595351c2..e6649981 100644 --- a/spid_cie_oidc/provider/tests/test_03_refresh_token.py +++ b/spid_cie_oidc/provider/tests/test_03_refresh_token.py @@ -72,7 +72,7 @@ def setUp(self): 'nonce': 'ljbvL3rpscgS4ZGda7cgibXHr7vrNREW', 'at_hash': '', 'c_hash': 'tij0h-zL_bSrsVXy-d3qHw', - 'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],], + 'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"], ], 'iss': op_conf["sub"], 'jti': '402e61bd-950c-4934-83d4-c09a05468828', 'exp': exp_from_now(), @@ -81,7 +81,7 @@ def setUp(self): access_token = { 'iss': op_conf["sub"], 'sub': '2ed008b45e66ce53e48273dca5a4463bc8ebd036ebaa824f4582627683c2451b', - 'aud': [rp_conf["metadata"]["openid_relying_party"]["client_id"],], + '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', @@ -108,9 +108,10 @@ def setUp(self): session=session, expires=timezone.localtime() ) + self.assertEqual(refresh_token["iss"], self.op_local_conf["sub"]) - @override_settings(OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME=1, OIDCFED_DEFAULT_PROVIDER_PROFILE="cie") - def test_grant_refresh_token_cie(self): + @override_settings(OIDCFED_PROVIDER_PROFILE="spid") + def test_grant_refresh_token_spid(self): client = Client() url = reverse("oidc_provider_token_endpoint") request = dict( @@ -126,6 +127,45 @@ def test_grant_refresh_token_cie(self): self.assertEqual(refresh_token["aud"], RP_CLIENT_ID) self.assertEqual(refresh_token["iss"], self.op_local_conf["sub"]) + @override_settings(OIDCFED_PROVIDER_PROFILE="cie") + def test_grant_refresh_token_cie(self): + client = Client() + url = reverse("oidc_provider_token_endpoint") + request = dict( + client_id=RP_CLIENT_ID, + client_assertion=self.ca_jws, + client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + refresh_token=self.rt_jws, + grant_type="refresh_token" + ) + res = client.post(url, request) + self.assertTrue(res.status_code == 200) + refresh_token = verify_jws(res.json().get("refresh_token"), op_conf_priv_jwk) + self.assertEqual(refresh_token["aud"], RP_CLIENT_ID) + + @override_settings(OIDCFED_PROVIDER_MAX_REFRESH=1, OIDCFED_PROVIDER_PROFILE="spid") + def test_grant_refresh_token_two_times_spid(self): + client = Client() + url = reverse("oidc_provider_token_endpoint") + request = dict( + client_id=RP_CLIENT_ID, + client_assertion=self.ca_jws, + client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + refresh_token=self.rt_jws, + grant_type="refresh_token" + ) + res = client.post(url, request) + self.assertTrue(res.status_code == 200) + request = dict( + client_id=RP_CLIENT_ID, + client_assertion=self.ca_jws, + client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", + refresh_token=res.json()["refresh_token"], + grant_type="refresh_token" + ) + res = client.post(url, request) + self.assertTrue(res.status_code == 400) + @override_settings(OIDCFED_PROVIDER_MAX_CONSENT_TIMEFRAME=1, OIDCFED_PROVIDER_PROFILE="cie") def test_grant_refresh_token_two_times_cie(self): client = Client() @@ -146,29 +186,6 @@ def test_grant_refresh_token_two_times_cie(self): refresh_token=res.json()["refresh_token"], grant_type="refresh_token" ) - time.sleep(1) + time.sleep(2) res = client.post(url, request) self.assertTrue(res.status_code == 400) - - # @override_settings(OIDCFED_PROVIDER_MAX_REFRESH=1, OIDCFED_PROVIDER_PROFILE="spid") - # def test_grant_refresh_token_two_times_spid(self): - # client = Client() - # url = reverse("oidc_provider_token_endpoint") - # request = dict( - # client_id=RP_CLIENT_ID, - # client_assertion=self.ca_jws, - # client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", - # refresh_token=self.rt_jws, - # grant_type="refresh_token" - # ) - # res = client.post(url, request) - # self.assertTrue(res.status_code == 200) - # request = dict( - # client_id=RP_CLIENT_ID, - # client_assertion=self.ca_jws, - # client_assertion_type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer", - # refresh_token=res.json()["refresh_token"], - # grant_type="refresh_token" - # ) - # res = client.post(url, request) - # self.assertTrue(res.status_code == 400) \ No newline at end of file diff --git a/spid_cie_oidc/provider/views/token_endpoint.py b/spid_cie_oidc/provider/views/token_endpoint.py index e5010588..51126b7d 100644 --- a/spid_cie_oidc/provider/views/token_endpoint.py +++ b/spid_cie_oidc/provider/views/token_endpoint.py @@ -97,8 +97,8 @@ def grant_auth_code(self, request, *args, **kwargs): return JsonResponse(iss_token_data) def is_token_renewable(self, session) -> bool: - logger.info(OIDCFED_DEFAULT_PROVIDER_PROFILE) - if OIDCFED_DEFAULT_PROVIDER_PROFILE == "cie": + provider = getattr(settings, "OIDCFED_PROVIDER_PROFILE") + if provider == "cie": issuedToken = IssuedToken.objects.filter( session=session ).first() @@ -112,7 +112,7 @@ def is_token_renewable(self, session) -> bool: if delta > 0: return True return False - elif OIDCFED_DEFAULT_PROVIDER_PROFILE == "spid": + elif provider == "spid": # TODO: check also ACR issuedToken = IssuedToken.objects.filter( session=session From 7b9bc923e9960841ea035ccbb91b818541cc00ca Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Wed, 26 Jul 2023 10:59:07 +0200 Subject: [PATCH 13/15] chore: custom SVG for SPID LTS and revised text for CIE --- .../static/svg/cie-ico-circle-bb-LTS.svg | 37 +++++++++++++++++++ .../relying_party/templates/rp_landing.html | 9 ++--- 2 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 spid_cie_oidc/relying_party/static/svg/cie-ico-circle-bb-LTS.svg diff --git a/spid_cie_oidc/relying_party/static/svg/cie-ico-circle-bb-LTS.svg b/spid_cie_oidc/relying_party/static/svg/cie-ico-circle-bb-LTS.svg new file mode 100644 index 00000000..45fe1935 --- /dev/null +++ b/spid_cie_oidc/relying_party/static/svg/cie-ico-circle-bb-LTS.svg @@ -0,0 +1,37 @@ + + + +Created with Fabric.js 5.2.4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Long Term Session + + \ No newline at end of file diff --git a/spid_cie_oidc/relying_party/templates/rp_landing.html b/spid_cie_oidc/relying_party/templates/rp_landing.html index 217ee3cb..0997295e 100644 --- a/spid_cie_oidc/relying_party/templates/rp_landing.html +++ b/spid_cie_oidc/relying_party/templates/rp_landing.html @@ -65,10 +65,9 @@

  • - {{ attrs.organization_name }} {% trans "LONG TERM SESSION" %} + {{ attrs.organization_name }} {% if attrs.logo_uri %} - {{ attrs.organization_name }} -

    {% trans "LONG TERM SESSION" %}

    + {{ attrs.organization_name }} {% else %} {{ sub }}

    {{ sub }}

    @@ -112,10 +111,10 @@

  • - {{ attrs.organization_name }} {% trans "LONG TERM SESSION" %} + {{ attrs.organization_name }} {% trans "INCLUDING REFRESH TOKEN" %} {% if attrs.logo_uri %} {{ attrs.organization_name }} -

    {% trans "LONG TERM SESSION" %}

    +

    {% trans "INCLUDING REFRESH TOKEN" %}

    {% else %} {{ sub }} From cb24a4c96b64d46ec8e297676a9e7b17cf07f145 Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Thu, 27 Jul 2023 20:06:44 +0200 Subject: [PATCH 14/15] chore: custom SVG for SPID LTS --- .../static/svg/spid-logo-c-lb.svg-LTS.svg | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 spid_cie_oidc/provider/static/svg/spid-logo-c-lb.svg-LTS.svg diff --git a/spid_cie_oidc/provider/static/svg/spid-logo-c-lb.svg-LTS.svg b/spid_cie_oidc/provider/static/svg/spid-logo-c-lb.svg-LTS.svg new file mode 100644 index 00000000..70d2caa2 --- /dev/null +++ b/spid_cie_oidc/provider/static/svg/spid-logo-c-lb.svg-LTS.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + LONG TERMSESSION + From 5caa145afc41105ed4f4fef8ae7eb75bc8325b7d Mon Sep 17 00:00:00 2001 From: rglauco <37829079+rglauco@users.noreply.github.com> Date: Tue, 1 Aug 2023 18:44:03 +0200 Subject: [PATCH 15/15] chore: better refresh token use description, differentiated between CIE and SPIE --- .../relying_party/templates/echo_attributes.html | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/spid_cie_oidc/relying_party/templates/echo_attributes.html b/spid_cie_oidc/relying_party/templates/echo_attributes.html index 2b25f83f..5242637c 100644 --- a/spid_cie_oidc/relying_party/templates/echo_attributes.html +++ b/spid_cie_oidc/relying_party/templates/echo_attributes.html @@ -51,18 +51,23 @@

    {% trans "Warning" %}:

    {% trans 'To enable revocable long sessions you must set OIDCFED_ACR_PROFILES in settingslocal.py of the Relying Party' %} OIDCFED_ACR_PROFILES=["https://www.spid.gov.it/SpidL2","https://www.spid.gov.it/SpidL1"]

    {% else %} -
    +

    ACCESS TOKEN

    {% trans "The" %} access token {{ at_jti }}
    {% trans "expires in" %} {{ at_expiration }}

    -
    +

    REFRESH TOKEN {% trans "Extend Session" %}

    {% trans "The" %} Refresh Token {{ rt_jti }}
    {% trans "expires in" %} {{ rt_expiration }}

    {% endif %}