Question

I am writing a custom authentication backend (and a custom user model) to check if a user account is locked or expired. I see that in all the examples of authentication backend return value is either a User object or None. And the only exception generated is User.DoesNotExist.

My question is how should I go about returning different results (e.g. account is locked or expired or max number of login attempts have reached)?

Should I raise custom exceptions or there is another way to do this?

I am using Django 1.5alpha.

EDIT: I need to get multiple statuses to display appropriate message to a user and redirect to an appropriate view.

Was it helpful?

Solution 2

I ended up doing this in case anyone has the same question.

class UserNotActivatedError(Exception):
    pass

class UserLockedError(Exception):
    def __init__(self, remaining_mins):
        self.remaining_mins = remaining_mins

# backend
def authenticate(self, email=None, password=None):
    if email is None or password is None:
        return None
    try:
        user = ExtUser.objects.get(email=email)
        user.last_login_attempt_at = timezone.now()
        if not use.is_active:
            raise UserNotActivatedError
        if user.is_locked:
            # Check when it was locked and found the duration
            sec_to_go = user.get_remaining_locktime()
            if sec_to_go:
                raise UserLockedError(sec_to_go)
        if user.check_password(password):
            user.last_login_at = timezone.now() 
            return user
        else:
            return None
    except User.DoesNotExist:
        return None

Then in the login form you can catch these errors and pass on appropriate validation errors to the view.

OTHER TIPS

As noted in the docs:

Either way, authenticate should check the credentials it gets, and it should return a User object that matches those credentials, if the credentials are valid. If they're not valid, it should return None.

An account that is locked, expired, or has reached its max number of login attempts would be considered "invalid", and so None should be returned for those conditions.

Basically, None should be returned whenever a login should be denied access (for whatever reason).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top