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 56f707e7..e10ecbd9 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 @@ -2,6 +2,8 @@ import jwt from django.contrib.auth.models import User +from asgiref.sync import iscoroutinefunction +from django.utils.decorators import sync_and_async_middleware from keycloak.exceptions import KeycloakGetError @@ -36,20 +38,56 @@ def _get_user(): return None -class BearerTokenMiddleware: - def __init__(self, get_response=None): - # One-time configuration and initialization. - self.get_response = get_response +async def _aget_user(): + bearer = get_authentication_token() + if bearer: + # found bearer token get the Django user + try: + token = bearer.split(" ")[-1] + payload = jwt.decode(token, algorithms=["RS256"], options={"verify_signature": False}, audience="web-client") + kc_id = payload["sub"] + try: + user = await User.objects.aget(member__kc_id=kc_id) + except User.DoesNotExist: + user = await get_user_service().async_kc_user(get_auth_service().get_auth_client().get_current_user()) + return user + except KeycloakGetError: + # KC user not found + return None + except InvalidToken: + return None + except Exception as e: + log.exception("User mapping error, %s", payload["email"]) + return None + + return None + + +@sync_and_async_middleware +def BearerTokenMiddleware(get_response=None): + # One-time configuration and initialization. + if iscoroutinefunction(get_response): + async def middleware(request): + if (not request.path.startswith("/static")) and getattr(getattr(request, "user", {}), "is_anonymous", True): + user = await _aget_user() + if user: + # auto login, set the user + request.user = user + request._cached_user = user - def __call__(self, request): - if getattr(getattr(request, "user", {}), "is_anonymous", True): - user = _get_user() - if user: - # auto login, set the user - request.user = user - request._cached_user = user + response = await get_response(request) + return response + else: + def middleware(request): + if (not request.path.startswith("/static")) and getattr(getattr(request, "user", {}), "is_anonymous", True): + user = _get_user() + if user: + # auto login, set the user + request.user = user + request._cached_user = user - return self.get_response(request) + return get_response(request) + return middleware class BearerTokenAuthentication: diff --git a/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/user.py b/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/user.py index 189e6516..b63be738 100644 --- a/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/user.py +++ b/infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/user.py @@ -107,6 +107,16 @@ def sync_kc_user(self, kc_user, is_superuser=False, delete=False): user.save() return user + async def async_kc_user(self, kc_user, is_superuser=False, delete=False): + # sync the kc user with the django user + + user, created = await User.objects.aget_or_create(username=kc_user["username"]) + + await Member.objects.aget_or_create(user=user, kc_id=kc_user["id"]) + user = self._map_kc_user(user, kc_user, is_superuser, delete) + user.save() + return user + def sync_kc_user_groups(self, kc_user): # Sync the user usergroups and memberships user = User.objects.get(username=kc_user["email"])