Can't login in django admin using custom user

I create a custom model for User.
I can create a superuser using command line and its created successfully.

But when I try to login in django admin it does not redirect to the django admin itself.

I already verified that it is authenticating properly.

Here is the backend authentication created

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q

User = get_user_model()

class AuthBackend(ModelBackend):
    supports_object_permissions = True
    supports_anonymous_user = False
    supports_inactive_user = False

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

    def authenticate(self, request, username=None, password=None, **kwargs):
        print('inside custom auth')
        try:
            user = User.objects.get(
                Q(nif=username))
            print(user)
        except User.DoesNotExist:
            print('teste')
            return None

        if user.check_password(password):
            print('ok', user, password, **kwargs)
            print(self.user_can_authenticate(user))
            return user
        else:
            print('nok', user, password)
            return None

My app is on apps/usuarios.

Here is my configuration on settings:


DEBUG = True

ALLOWED_HOSTS = []

AUTH_USER_MODEL = "usuarios.User"

AUTHENTICATION_BACKENDS = [
    #"django.contrib.auth.backends.ModelBackend",
    "apps.usuarios.backend.AuthBackend",
]

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps.usuarios.apps.UsuariosConfig',
]


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',
]

ROOT_URLCONF = 'setup.urls'

I think it is a problem with redirection but I can’t figured what is causing this.
What I am missing?

In the authentication method I put a debug to show if the user was authenticate properly and it is working, it gives no error on the screen.
I also verified in shell that the custom super user created is with is_staff True and is_superuser True and is_active True.

To debug if it was passing through the authenticate method on the backends correctly, I did this:

I created a user with NIF 1234567 and password 0000

If I try to login correctly the page shows no error but do not redirect to django admin and the terminal shows this:

inside custom auth

1234567

ok 1234567 0000

True

[03/Dec/2023 20:24:21] “POST /admin/login/?next=/admin/ HTTP/1.1” 302 0

[03/Dec/2023 20:24:21] “GET /admin/ HTTP/1.1” 302 0

[03/Dec/2023 20:24:21] “GET /admin/login/?next=/admin/ HTTP/1.1” 200 4207

If I try with an invalid nif and password the page shows the error correctly and here is the terminal:

inside custom auth

1234567

nok 1234567 1111

[03/Dec/2023 20:26:07] “POST /admin/login/?next=/admin/ HTTP/1.1” 200 4392

Hey there!
I would double check if the user is actually marked with is_staff, even though you said it’s checked.
Maybe the best place would be here:

Thanks for the repply. I tested and these 3 fields is True:
is_active
is_staff
is_superuser

Hi, is the nif field the primary key of your user model ?

As stated in documentation (see Customizing authentication in Django | Django documentation | Django) the parameter of the get_user method “has to be the primary key of your user object”.

Here, I think that after login, your user cannot be retrieved from pk saved in session as get_user returns None because it tried to match the nif with a value corresponding to primary key.

I think you do not need to override get_user.

You found exactly what I was missing, I changed my model putting the primary_key on the nif.

Nif field before:

nif_validator = RegexValidator(
        regex='^[1-9]{1}[0-9]{5,6}$',
        message="Invalid NIF (Valid pattern: 1234567",
    )
nif = models.CharField(
        _("NIF"),
        max_length=7,
        unique=True,
        validators=[nif_validator],
        blank=False,
        null=False,
        error_messages={
            "unique": _("NIF already registered in the system"),
            "validators": _("Invalid NIF (Valid pattern: 1234567"),
        },
    )

NIF Field after:

nif_validator = RegexValidator(
        regex='^[1-9]{1}[0-9]{5,6}$',
        message="Invalid NIF (Valid pattern: 1234567",
    )
nif = models.CharField(
        _("NIF"),
        max_length=7,
        primary_key=True, # <---- Added line to resolve login issue in Django Admin
        unique=True,
        validators=[nif_validator],
        blank=False,
        null=False,
        error_messages={
            "unique": _("NIF already registered in the system"),
            "validators": _("Invalid NIF (Valid pattern: 1234567"),
        },
    )