Skip to main content

Django User.is_authenticated may not do what you think

Django’s User.is_authenticated may not behave as you expect. When exploring some model relationships, I was surprised that every user in the system seemed to be authenticated.

>>> from .models import User
>>> User.objects.first().is_authenticated
True

Initially, I was confused as to why this was the case, thinking this implied the user had a current session within the system.

Looking at the code quickly explained why this was the case:

class AbstractBaseUser(models.Model):
    ...

    @property
    def is_anonymous(self):
        """
        Always return False. This is a way of comparing User objects to
        anonymous users.
        """
        return False

    @property
    def is_authenticated(self):
        """
        Always return True. This is a way to tell if the user has been
        authenticated in templates.
        """
        return True

This makes sense once you consider the context that this method is expected to be used in: within Django’s session when rendering templates. It is there to determine whether the user has authenticated themself to the system, and proven their identity within that session. Outside of that context, it probably shouldn’t be used.

This is covered in the documentation:

Read-only attribute which is always True (as opposed to AnonymousUser.is_authenticated which is always False). This is a way to tell if the user has been authenticated. This does not imply any permissions and doesn’t check if the user is active or has a valid session.

It serves as a reminder that implementation details may conflict with our initial expectations.