4

I want to create an authentication for my Django 1.11 project. A user will be authenticated if the request contains the header : X_USERNAME. I am working with generic views so I use LoginRequiredMixin to control access.

I made this Custom authentication class:

class CustomAuthentication:
    def authenticate(self, request):
        username = request.META.get('X_USERNAME')
        logging.warning(username)
        if not username:
            return None
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            user = User(username=username)
            user.is_staff = False
            user.is_superuser = False
            if request.META.get('X_GROUPNAME') == 'administrator':
                user.is_staff = True
                user.is_superuser = True
            user.save()
        return user, None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

I added it in my settings :

AUTHENTICATION_BACKENDS = ['path.to.file.CustomAuthentication']

But I can't make it work. I am redirected to /accounts/login/?next= which doesn't exist.

Thanks in advance!

EDIT:

I also tried to create a subclass as described here : Django RemoteUser documentation since it looks like what I want to achieve:

class CustomAuthentication(RemoteUserMiddleware):
    header = 'HTTP_X_USERNAME'

It gave me the same result.

2
  • Have you tried placing additional log statements within the authenticate() method to see what code path is being executed? Commented Nov 5, 2018 at 17:55
  • Yes I did, It seems that this function is never called. Maybe the authenticate() method should be called manually within a login page ? Which is not what I want since I don't want to use a login page. Commented Nov 6, 2018 at 8:13

2 Answers 2

3

I finally managed to find a solution :

In authentication.py:

from django.contrib.auth.middleware import RemoteUserMiddleware

class CustomMiddleware(RemoteUserMiddleware):
    header = 'HTTP_X_USERNAME'

The second import is compulsory i am not sure why.

In settings.py:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'app.authentication.CustomMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

AUTHENTICATION_BACKENDS = ['app.authentication.RemoteUserBackend']

And finally in the class based views I use LoginRequiredMixin

See: https://docs.djangoproject.com/en/3.2/howto/auth-remote-user/#configuration

Sign up to request clarification or add additional context in comments.

1 Comment

No longer seems to be working: Attribute Error: ... object has no attribute 'authenticate'
0

It seems that the authenticate() method must specify username and password arguments in addition to the request argument. Without these, Django ignores the backend (see django.contrib.auth.__init__._authenticate_with_backend in Django 2.0).

In your case you should be able to default these arguments to None since you're providing the username via a header.

class CustomAuthentication:
    def authenticate(self, request, username=None, password=None):
        username = request.META.get('X_USERNAME')
        ...

Alternatively, use **credentials:

def authenticate(self, request, **credentials):

2 Comments

I tried it but the authenticate() method is still not executed. I think I am not using the right kind of authentication. Still, this is a useful piece of information.
Strange. When I leave out the username and password attributes from my test backend the authenticate() method does not get called, otherwise Django calls it fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.