[Django]-Django admin not working with custom auth backend

8👍

I found the answer myself.

After digging into Django’s source code, I find this snippet in django.contrib.auth.forms that handles the post request from admin site’s login form:

def clean(self):
    username = self.cleaned_data.get('username')
    password = self.cleaned_data.get('password')

    if username and password:
        self.user_cache = authenticate(username=username,
                                       password=password)
        if self.user_cache is None:
            raise forms.ValidationError(
                self.error_messages['invalid_login'],
                code='invalid_login',
                params={'username': self.username_field.verbose_name},
            )
        else:
            self.confirm_login_allowed(self.user_cache)

    return self.cleaned_data

Notice that although it uses auth.authentication to handle the login action, it actually parses fixed fields username and password, which means the default admin site login form neglects your own AuthenticationBackends.

To solve this, I need to implement my own login-form for admin site.

5👍

This is my solution.. hope it will help someone:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend' #add this line
    'your auth backend'
]

the default django.contrib.auth.backends.ModelBackend class is retained to ensure the default username / password authentication workflow used by the django administration. Then your custom authentication back-end class is added, so you can make your changes.

0👍

I got exactly the same issue when using a custom model with email authentification. I manage to solve this issue by creating a new backend class.
From what I understand, django is looping over all the backends defined in your application checking if any has the exact import paramaters.

In you case, maybe something like that will work

class EmailAdminBackend(ModelBackend):
def authenticate(self, request, username=None, password=None):
    UserModel = get_user_model()
    try:
        # Check if the user exists in Django's database
        user = UserModel.objects.get(openid=username)
    except :
        return None
    if user.check_password(password):
        return user
    return None

0👍

Although it is late answer, it can help someone:
How you customize the authentication backend it doesn’t matter. But one thing you should remember in mind that you have to include ModelBacked in AUTHENTICATION_BACKENDS. Otherwise you can’t login to your django admin.

Now your AUTHENTICATION_BACKENDS should look like:

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'BBUser.models.AdminAuthBackend',
    ]
👤babor

Leave a comment