Reputation: 79
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.
Upvotes: 4
Views: 2289
Reputation: 79
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
Upvotes: 3
Reputation: 23054
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):
Upvotes: 0