import logging import requests from django.conf import settings from django.contrib import auth from django.core.exceptions import ImproperlyConfigured from django.shortcuts import render from core_images.domains import get_allowed_root_domain from core_images.exceptions import AccessDeniedError, BearerTokenExpiredError logger = logging.getLogger(__name__) class AtlasAuthMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): if request.path.startswith(settings.ATLAS_AUTH_EXCLUDE_URL_PREFIX): return self.get_response(request) # AuthenticationMiddleware is required so that request.user exists. if not hasattr(request, "user"): raise ImproperlyConfigured( "The Django remote user auth middleware requires the" " authentication middleware to be installed. Edit your" " MIDDLEWARE setting to insert" " 'django.contrib.auth.middleware.AuthenticationMiddleware'" " before the RemoteUserMiddleware class." ) new_token = None new_refresh_token = None try: bearer_token = request.COOKIES[ settings.ATLAS_BEARER_TOKEN_COOKIE_NAME ] refresh_token = request.COOKIES[ settings.ATLAS_REFRESH_TOKEN_COOKIE_NAME ] except KeyError: # If specified cookie doesn't exist then remove any existing # authenticated atlas user, or return (leaving request.user set to # AnonymousUser by the AuthenticationMiddleware). if request.user.is_authenticated: auth.logout(request) return self.get_response(request) try: user = auth.authenticate( request, token=bearer_token, refresh_token=refresh_token, ) except BearerTokenExpiredError: new_token, new_refresh_token = update_token( refresh_token, ) try: user = auth.authenticate( request, token=new_token, refresh_token=new_refresh_token, ) except AccessDeniedError: return render( request, "401.html", status=401, context={"site_header": "Core Images Service"}, ) except AccessDeniedError: return render( request, "401.html", status=401, context={"site_header": "Core Images Service"}, ) if user: # User is valid. Set request.user and persist user in the session # by logging the user in. request.user = user auth.login(request, user) else: auth.logout(request) return self.get_response(request) response = self.get_response(request) if new_token and new_refresh_token: domain = get_allowed_root_domain(request) domain_cookie = f".{domain}" if domain else None response.set_cookie( settings.ATLAS_BEARER_TOKEN_COOKIE_NAME, new_token, httponly=True, domain=domain_cookie, secure=True, max_age=settings.TOKEN_COOKIES_MAX_AGE, ) response.set_cookie( settings.ATLAS_REFRESH_TOKEN_COOKIE_NAME, new_refresh_token, httponly=True, domain=domain_cookie, secure=True, max_age=settings.TOKEN_COOKIES_MAX_AGE, ) return response def update_token(refresh_token): try: atlas_resp = requests.post( settings.ATLAS_REFRESH_TOKEN_URL, data={ "refresh_token": refresh_token, "resource_group": settings.RELATED_CLAIMS_NAMESPACE, }, ) except Exception as e: logger.error(f"Error on token refresh: {e}") return None, None if atlas_resp.status_code != 200: logger.warning(f"Failed to refresh the token: {atlas_resp.content}") return None, None data = atlas_resp.json() bearer_token = data.get("access_token", "") refresh_token = data.get("refresh_token", "") if not bearer_token or not refresh_token: logger.warning(f"Received no tokens: {atlas_resp.content}") return None, None return bearer_token, refresh_token