Search code examples
pythondjangoauthenticationdjango-authentication

authenticate() is not running with custom authentication backend


I' m trying to add a new authentication backend to my project with the following versions and code snippets:

django: 2.2.1 python: 3.5.2 mysql-server: 5.7

settings.py

...
AUTHENTICATION_BACKENDS = ['common.backends.MyOwnAuthenticationBackend']

common/backends.py

from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.models import User


class MyOwnAuthenticationBackend(ModelBackend):
    print('MOAB')
    def authenticate(self, username=None, password=None):
        print('AUTH')
        ...

    def get_user(self, username):
        print('GETUSER')
        try:
            return User.objects.get(pk=username)
        except User.DoesNotExist:
            return None

While trying to log in, i get back the MOAB, but none of the AUTH or GETUSER strings.

What can be the reason for it?

The main urls.py contains the following for authentication:

urls.py

from common import views as common_views
from django.conf.urls import include, url
from django.contrib import admin
from django.contrib.auth import views
from django.urls import path

...

url(r'^accounts/login/$', views.LoginView, name='auth_login'),

...

What did i miss? I read many questions and posts about it on the Internet, but i can' t figure out why the authenticate() method is not called at all.


Solution

  • The method should look like :

    def authenticate(self, request, username=None, password=None):
    

    You can can check the parameters needed for the signature of the method authenticate by looking at the source of authentication system. The first positioned parameter is request, and then the credentials are unpacked as named parameters:

    def authenticate(request=None, **credentials):
        """
        If the given credentials are valid, return a User object.
        """
        for backend, backend_path in _get_backends(return_tuples=True):
            try:
                inspect.getcallargs(backend.authenticate, request, **credentials)
            except TypeError:
                # This backend doesn't accept these credentials as arguments. Try the next one.
                continue
            try:
                user = backend.authenticate(request, **credentials)
         [...]
    

    (_get_backends represents the list of all backends in settings.AUTHENTICATION_BACKENDS)

    Doc about custom authentication :
    https://docs.djangoproject.com/en/dev/topics/auth/customizing/#writing-an-authentication-backend