diff --git a/boxes/tests.py b/boxes/tests.py index 9212e99..1bbf829 100644 --- a/boxes/tests.py +++ b/boxes/tests.py @@ -1,14 +1,31 @@ +from types import SimpleNamespace + from django.contrib.admin.sites import AdminSite from django.contrib.auth.models import User from django.core.files.uploadedfile import SimpleUploadedFile from django.db import IntegrityError -from django.test import Client, TestCase +from django.test import Client, RequestFactory, SimpleTestCase, TestCase from django.urls import reverse +from mozilla_django_oidc.middleware import SessionRefresh from .admin import BoxAdmin, BoxTypeAdmin, ThingAdmin from .models import Box, BoxType, Facet, Tag, Thing, ThingFile, ThingLink +class OIDCSessionRefreshTests(SimpleTestCase): + """Tests for OIDC session refresh routing exclusions.""" + + def test_media_urls_do_not_trigger_oidc_session_refresh(self): + """Uploaded files should be served directly, not redirected through OIDC.""" + request = RequestFactory().get('/media/things/files/251/diag_6606.png') + request.user = SimpleNamespace(is_authenticated=True) + request.session = {} + + middleware = SessionRefresh(lambda request: None) + + self.assertFalse(middleware.is_refreshable_url(request)) + + class AuthTestCase(TestCase): """Base test case that provides authenticated client.""" diff --git a/labhelper/settings.py b/labhelper/settings.py index 2260525..1eed89f 100644 --- a/labhelper/settings.py +++ b/labhelper/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/5.2/ref/settings/ """ import os +import re from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -181,5 +182,13 @@ OIDC_STORE_ID_TOKEN = True # Redirect to the static login page on auth failure instead of looping back into OIDC OIDC_AUTHENTICATION_FAILURE_REDIRECT_URL = os.environ.get('OIDC_AUTHENTICATION_FAILURE_REDIRECT_URL', '/login/') -# Exempt AJAX endpoints from the session-refresh middleware redirect -OIDC_EXEMPT_URLS = ['search_api'] +# Exempt endpoints and uploaded media from the session-refresh middleware. +# +# Media URLs are already served without a login_required view. If an embedded +# image request is redirected into a silent OIDC refresh, the callback happens +# in a subresource context and browsers can withhold the session cookie, causing +# the OIDC state check to fail with HTTP 400. +OIDC_EXEMPT_URLS = [ + 'search_api', + re.compile(rf'^{re.escape(MEDIA_URL)}'), +]