diff --git a/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/middleware.py b/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/middleware.py index 9b2d7084..a2c5b40e 100644 --- a/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/middleware.py +++ b/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/middleware.py @@ -4,6 +4,8 @@ from django.contrib.auth.models import User from django.contrib.auth import logout from django.db import transaction +from django.core.cache import cache +from django.conf import settings from keycloak.exceptions import KeycloakGetError from cloudharness.auth.exceptions import InvalidToken @@ -14,6 +16,9 @@ from psycopg2.errors import UniqueViolation +USER_CACHE_TTL = getattr(settings, "BEARER_TOKEN_USER_CACHE_TTL", 60) + + def _get_user(kc_user_id: str) -> User: """ Get or create a Django user for the given Keycloak user ID. @@ -108,7 +113,7 @@ def __init__(self, get_response=None): @transaction.atomic def __call__(self, request): - user = getattr(request, "user", None) + authentication_token = get_authentication_token() if not authentication_token or authentication_token == 'Bearer undefined': return self.get_response(request) @@ -121,6 +126,16 @@ def __call__(self, request): response.delete_cookie('kc-access') return response + if kc_user_id: + cache_key = f"bearer_token_user:{kc_user_id}" + cached_user = cache.get(cache_key) + if cached_user: + request.user = cached_user + request._cached_user = cached_user + return self.get_response(request) + + user = getattr(request, "user", None) + if kc_user: if not user or user.is_anonymous or getattr(user, "member", None) is None or user.member.kc_id != kc_user_id: user = _get_user(kc_user_id) @@ -132,6 +147,7 @@ def __call__(self, request): # Safe to assign - user has a valid Member request.user = user request._cached_user = user + except: # This should NEVER happen due to _get_user safety checks, # but if it does, DO NOT assign the user - keep anonymous @@ -140,7 +156,8 @@ def __call__(self, request): # Don't assign user - request will remain anonymous # elif not request.path.startswith('/admin/'): # logout(request) - + if kc_user_id: + cache.set(cache_key, user, timeout=USER_CACHE_TTL) return self.get_response(request)