How to prevent multiple login in Django

I think you make things very complicated, by storing data in UserProfiles, etc. and then have signals, you introduce a lot of levels, and at each level, things can go wrong.

We basically need two things here: a table that maps Users to their corresponding settings. We can implement this with a UserSession model:

# models.py

from django.conf import settings
from django.db import models
from django.contrib.sessions.models import Session

class UserSession(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    session = models.OneToOneField(Session, on_delete=models.CASCADE)

So the UserSession object makes a link between User and Sessions. Now we can implement a login hook: a signal that is triggered in case a user logs in. In that case we perform two things:

  1. we delete all Sessions (and corresponding UserSessions) of the User that are active; and
  2. we create a new Session and corresponding UserSession that we can remove later. Like:
from django.contrib.auth import user_logged_in
from django.dispatch.dispatcher import receiver

@receiver(user_logged_in)
def remove_other_sessions(sender, user, request, **kwargs):
    # remove other sessions
    Session.objects.filter(usersession__user=user).delete()

    # save current session
    request.session.save()

    # create a link from the user to the current session (for later removal)
    UserSession.objects.get_or_create(
        user=user,
        session=Session.objects.get(pk=request.session.session_key)
    )

Tags:

Session

Django