Manually logging in a user without password Manually logging in a user without password django django

Manually logging in a user without password


You don't need a password to log a user in. The auth.login function just takes a User object, which you are presumably already getting from the database when you enable the account. So you can pass that straight to login.

Of course, you'll need to be very careful that there's no way a user can spoof a link to an existing already-enabled account, which would then automatically log them in as that user.

from django.contrib.auth import logindef activate_account(request, hash):    account = get_account_from_hash(hash)    if not account.is_active:        account.activate()        account.save()        user = account.user        login(request, user)

... etc.

Edited:

Hmm, didn't notice that requirement to use authenticate because of the extra property it adds. Looking at the code, all it does is a backend attribute equivalent to the module path of the authenticating backend. So you could just fake it - before the login call above, do this:

user.backend = 'django.contrib.auth.backends.ModelBackend'


As of Django 1.10, the process has been simplified.

In all versions of Django, in order for a user to be logged in, they must be authenticated by one of your app's backends (controlled by the AUTHENTICATION_BACKENDS setting).

If you simply want to force a login, you can just claim that the user was authenticated by the first backend from that list:

from django.conf import settingsfrom django.contrib.auth import login# Django 1.10+login(request, user, backend=settings.AUTHENTICATION_BACKENDS[0])# Django <1.10 -  fake the authenticate() calluser.backend = settings.AUTHENTICATION_BACKENDS[0]login(request, user)


Daniel's answer is very good.

Another way to do it is to create a HashModelBackend following the Custom Authorization backends https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#writing-an-authentication-backend like this:

class HashModelBackend(object):    def authenticate(self, hash=None):        user = get_user_from_hash(hash)        return user    def get_user(self, user_id):        try:            return User.objects.get(pk=user_id)        except User.DoesNotExist:            return None

And then install this in your settings:

AUTHENTICATION_BACKENDS = (    'myproject.backends.HashModelBackend',    'django.contrib.auth.backends.ModelBackend',)

Then your view would be something like this:

def activate_account(request, hash):    user = authenticate(hash=hash)    if user:        # check if user is_active, and any other checks        login(request, user)    else:        return user_not_found_bad_hash_message