Django Login Middleware
Tags: python, django, middleware
Published: 2019-09-03 14:41:13

---
title: Django Login Middleware
published: true
tags: python, django, middleware
canonical_url: https://tech.serhatteker.com/post/2019-02/django-login-middleware/
---

Django provides a decorator called `login_required` that takes one of your views and prevents a user from seeing it unless they are authenticated. Every time we need to add this decorator above view. Usually it’s a real pain to use the `login_required` decorator all over the views of your sophisticated site. What if you forget to add it to view that contains sensitive information?

Django allows you to write custom middleware that gets access to each request so you can add functionality that can be applied to your whole site. My middleware simply intercepts each request and redirects users to the site login page, `LOGIN_URL` if they haven’t logged in. It also allows you to give of exceptions, i.e. pages that can be viewed without authenticated.

First create `LoginRequiredMiddleware.py` file:


```python
import re

from django.conf import settings
from django.http import HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import is_safe_url


EXEMPT_URLS = [re.compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
    EXEMPT_URLS += [re.compile(url) for url in settings.LOGIN_EXEMPT_URLS]


class LoginRequiredMiddleware(MiddlewareMixin):
    def process_request(self, request):
        assert hasattr(request, 'user'), "The Login Required Middleware"
        if not request.user.is_authenticated:
            path = request.path_info.lstrip('/')
            if not any(m.match(path) for m in EXEMPT_URLS):
                redirect_to = settings.LOGIN_URL
                # 'next' variable to support redirection to attempted page after login
                if len(path) > 0 and is_safe_url(
                    url=request.path_info, allowed_hosts=request.get_host()):
                    redirect_to = f"{settings.LOGIN_URL}?next={request.path_info}"

                return HttpResponseRedirect(redirect_to)

```


Add this middleware in the core directory of your project. Such as:

```
└── project_root
    ├── manage.py
    ├── src
    │   ├── api
    │   ├── app
    │   └── core
    │   │   └── LoginRequiredMiddlware.py
    │   ├── static
    │   ├── templates
    │   └── users
    └── tests
        └── test_users.py
```


Then add this middleware in your settings file, `settings.py`.

```python
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    # login middleware
    'src.core.middleware.LoginRequiredMiddleware',
]
```

If you want to add other exception pages, pages that can be viewed without authentication, you can add those urls into `LOGIN_EXEMPT_URLS` in your settings:

```python
LOGIN_EXEMPT_URLS = (
    r'^home/$',
    r'^register/$',
    r'^pricing/$',
)
```

P.S: The `LoginRequiredMiddleware` requires authentication middleware to be installed. Edit your `MIDDLEWARE` setting to insert `'django.contrib.auth.middleware.AuthenticationMiddleware'`. If that doesn't work, ensure your `TEMPLATE_CONTEXT_PROCESSORS` setting includes `'django.core.context_processors.auth'`

For further details:
[MIDDLEWARE][1] and [TEMPLATE_CONTEXT_PROCESSORS][2]

[1]: https://docs.djangoproject.com/en/dev/ref/settings/#middleware
[2]: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors