Add a Setting to Exempt URLs in `LoginRequiredMiddleware`

With the introduction of LoginRequiredMiddleware in Django 5.1 (docs), I’ve run into an issue where certain URLs—like those from third-party libraries—are unintentionally blocked, even though they’re not meant to require authentication.

For example, URLs provided by third-party apps like Django REST Framework (DRF) or django-invitations are controlled by the app itself, so modifying their source code to exempt them from authentication isn’t an option. To work around this, I’ve subclassed the middleware to allow specific URL patterns to bypass authentication. I adapted this solution from a discussion in the DRF repository (link). Here’s my implementation:

import re
from django.conf import settings
from django.contrib.auth.middleware import LoginRequiredMiddleware

class CustomLoginRequiredMiddleware(LoginRequiredMiddleware):
    def __init__(self, get_response=None):
        self.get_response = get_response
        self.open_urls = [re.compile(url) for url in settings.OPEN_URLS]
        super().__init__(get_response)

    def process_view(self, request, view_func, view_args, view_kwargs):
        for url in self.open_urls:
            if url.match(request.path):
                return None  # Skip auth
        return super().process_view(request, view_func, view_args, view_kwargs)

In settings.py:

OPEN_URLS = [
    r"^/api/.*",
    r"^/invitations/accept-invite/.*$",
    # ...
]

This approach works, but I think it would be helpful if Django provided a built-in setting (e.g., LOGIN_REQUIRED_EXEMPT_URLS) to define these patterns directly in settings.py, without needing to subclass the middleware. This would make it much easier to handle cases where third-party apps expose URLs that shouldn’t require authentication.

Would this be a useful addition? If so, should I open a ticket on Trac to propose this feature?

I agree that it seems like something needs to be added here to allow for the types of situations that @abe has pointed out. I’d be curious if others have run into this with other libraries (maybe with django-ninja) and if their solutions are similar to the one offered for DRF

FYI, @abe it looks like the link to the DRF discussion isn’t working. I think this is because issues and discussions have been removed from the drf repository

1 Like

I would suggest investigating other ways to solve this. A separate list of paths that controls whether authentication happens feels likely to cause problems trying to keep the entire two separate collections in sync. I think it’d be better to that defined on the urlpatterns themselves or in the views.

The solution here may also be to patch the third-party libraries to better support LoginRequiredMiddleware.

1 Like

I think this is the way. Here’s an example implementation of a backwards compatible decorator for views:

try:
    from django.contrib.auth.decorators import login_not_required
except ImportError:
    # For Django < 5.1, copy the current Django implementation
    def login_not_required(view_func):
        """
        Decorator for views that allows access to unauthenticated requests.
        """
        view_func.login_required = False
        return view_func

I’ve added this to projects I maintain, for example here.

I think there’s a lot of hesitation these days to adding new settings, especially when adding the relevant code to your own project seems like a sensible way to go.

4 Likes

Thanks for your suggestion/solution

I’ve opened up GH issues on 2 projects i’ve ran into this issue with:

1 Like