0

I am trying to log in to a database that is not the default database, and for that I've wrote a custom authentication code but whenever I try to login the method returns an AnonymousUser. I've no idea why is it doing so because user authentication is done properly using the authenticate method.

Any help would be really appreciated.

MY FILES

views.py

def login_authentication(request):
    if request.method == "POST":
        form = New_Login_Form(request.POST)
        # print(request.POST)
        if form.is_valid():
            email = request.POST['email']
            password = request.POST['password']
            user_operating_company = request.POST['user_operating_company']
            user = authenticate(request, email=email,
                                password=password, db=user_operating_company)
            if user:
                login(request, user, user_operating_company)
                return redirect('test')
    else:
        form = New_Login_Form()
        return render(request, 'index.html', {'form': form})

backends.py

from django.contrib.auth.backends import ModelBackend
from .models import Account

class CustomAuthenticate(ModelBackend):
    def authenticate(self, request, email=None, password=None, db=None):
        try:
            user = Account.objects.all().using(db).get(email=email)
            if user.check_password(password):
                return user
        except:
            return None

    def get_user(self, request, email, db):
        try:
            return Account.objects.using(db).get(pk=email)
        except:
            return None

and in the

settings.py

AUTHENTICATION_BACKENDS = ('accounts.backends.CustomAuthenticate', 'django.contrib.auth.backends.ModelBackend')

EDIT:

I made the changes as per @schillingt 's answer the updated backend is:

from django.contrib.auth.backends import ModelBackend
from .models import Account

class CustomAuthenticate(ModelBackend):
    def authenticate(self, request, email=None, password=None, db=None):
        self.db = db
        try:
            user = Account.objects.using(db).get(email=email)
            if user.check_password(password):
                return user
        except Account.DoesNotExist:
            return None

    def get_user(self, email):
        try:
            user =  Account.objects.using(self.db).get(pk=email)
        except Account.DoesNotExist:
            return None
        return user if self.user_can_authenticate(user) else None

But now it gives me an error which says

'CustomAuthenticate' object has no attribute 'db'
Shaikh Abuzar
  • 101
  • 1
  • 9
  • I would recommend checking up on the [Multuple databases setion](https://docs.djangoproject.com/en/3.1/topics/db/multi-db/) at the Django Docs. Also, are you sure the user is also *created* in the separate database? – Johan Sep 22 '20 at 16:01
  • Yes I'm sure, as I've manually created it in a seperate database. – Shaikh Abuzar Sep 22 '20 at 16:43

1 Answers1

0

I believe you have the wrong signature for get_user. ModelBackend's is:

def get_user(self, user_id):
    try:
        user = UserModel._default_manager.get(pk=user_id)
    except UserModel.DoesNotExist:
        return None
    return user if self.user_can_authenticate(user) else None

This method is used by django.contrib.auth.get_user. Does your backend have a reference to the db instance that should be used? Or is that defined on the request? If it's defined on the request, you may have to monkey patch the django.contrib.auth.get_user method to supply the proper parameters to the call to the backend's get_user method so that you have the right db instance.

Edit:

This makes it seem like I'm wrong. You shouldn't have to monkey patch django.contrib.auth.get_user. You should be able to set the db instance on the backend instance in authenticate, then utilize that in get_user.

schillingt
  • 13,493
  • 2
  • 32
  • 34