Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

login_and_otp_required decorator exception discovered whilst implementing autologout: AttributeError: 'AnonymousUser' object has no attribute 'is_verified' #542

Open
anchit-chandran opened this issue Jan 31, 2025 · 1 comment
Assignees

Comments

@anchit-chandran
Copy link
Contributor

anchit-chandran commented Jan 31, 2025

Probably because of something i've changed in branch anchit/auto-logout but just making a record

Was testing autologout and found this exception being raised (from a dashboard htmx partial but same for all requests):

ERROR [django.request] Internal Server Error: /get_simple_bar_chart_pcts_partial
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/project/npda/views/decorators.py", line 55, in sync_login_and_otp_required
    if check_otp(view, request):
       ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/project/npda/views/decorators.py", line 32, in check_otp
    if not user.is_verified():
           ^^^^^^^^^^^^^^^^
AttributeError: 'AnonymousUser' object has no attribute 'is_verified'

Inside our perms decorator, if anon, the user object becomes instance of [django.contrib.auth.models.AnonymousUser](https://docs.djangoproject.com/en/5.1/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser)

def login_and_otp_required():
    """
    Must have verified via 2FA
    """

    def check_otp(view, request):
        # Then, ensure 2fa verified
        user = request.user
        # Bypass 2fa if local dev, with warning message
        if settings.DEBUG and user.is_authenticated:
            logger.warning(
                "User %s has bypassed 2FA for %s as settings.DEBUG is %s",
                user,
                view,
                settings.DEBUG,
            )
            return True

        # Prevent unverified users
        if not user.is_verified():
            logger.info(
                "User %s is unverified. Tried accessing %s",
                user,
                view.__qualname__,
            )
            return False

        return True
@anchit-chandran anchit-chandran self-assigned this Jan 31, 2025
@anchit-chandran
Copy link
Contributor Author

anchit-chandran commented Jan 31, 2025

I think this is something to do with django-auto-logout logging user out -> the user object is no longer the otp user object, just AnonymousUser, which doesn't have the is_verified method

Fix in PR was adding additional check and safe access:

def login_and_otp_required():
    """
    Must have verified via 2FA
    """

    def check_otp(view, request):

...
  if not user.is_authenticated:
              logger.info(
                  "User %s is not authenticated. Tried accessing %s",
                  user,
                  view.__qualname__,
              )
              return False
  
          # Prevent unverified (from otp) users
          if hasattr(user, "is_verified") and not user.is_verified():
              logger.info(
                  "User %s is unverified. Tried accessing %s",
                  user,
                  view.__qualname__,
              )
              return False

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant