2

I am working on openedx(which runs on django) and the user will be redirected here from other site and i'm being given the hashed password from there. Authenticate(username,password) excepts raw password like "dragon" not the hashed one,

So I need to use the authenticate() with the hashed password so that I can get the ".backend" attribute and move on with my life.

When I use login(request,user) without the authenticate method. this error appears:

request.session[BACKEND_SESSION_KEY] = user.backend
AttributeError: 'User' object has no attribute 'backend'

So I need to use the authenticate function to get that .backend attribute in my user object.

user = authenticate(username=username, password=password) is the format of the authenticate function, the password here is a raw password like "abc", what I have is a hashed password (which is the way this "abc" password will be stored in db).

I am stuck now, is there a way to authenticate and login using hashed passwords in django?

Régis B.
  • 10,092
  • 6
  • 54
  • 90
Taranjeet Singh
  • 177
  • 1
  • 3
  • 13
  • While your question is quite valid, could you rephrase it a bit in order to make it easier for the reader to understand what happens and where. A short but complete code example helps a lot. – Ilja Everilä Jun 29 '16 at 12:21

2 Answers2

3

You can create a custom authentication backend for django and override its authenticate and get_user method to authenticate using hashed password and username.

Since hashed password is just another modelfield with text in it, you can lookup for users with username and the hash pass value in db.

Something like this should work:

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

class HashedPasswordAuthBackend(ModelBackend):

    def authenticate(self, username=None, password=None):
        try:
            return User.objects.get(username=username, password=password)
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

After that, Include the path of this auth backend in your project settings.

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'yourapp.backends.HashedPasswordAuthBackend',
]
v1k45
  • 8,070
  • 2
  • 30
  • 38
1

Open edX uses the ratelimitbackend.backends.RateLimitModelBackend for authentication, as we can see in the settings. This backend requires the un-hashed password for authentication.

If you wish to authenticate a user based on its hashed password, you need to create a new authentication backend, as described in the django documentation.

I suggest you draw some inspiration from the Django ModelBackend, as implemented in django.contrib.auth.backends.

The error you see relative to the missing backend attribute is something that I have experienced before. In the impersonate_user view of FUN (an Open edX project) this is how we solve this problem (note the comment inside the source code of the view function):

user = get_object_or_404(User, username=username, is_superuser=False, is_active=True)
user.backend = None
login(request, user)
Régis B.
  • 10,092
  • 6
  • 54
  • 90
  • In this case, session is closed immediately when page is routed to anywhere different from the current one. – LKM Aug 01 '16 at 00:50
  • This is not what I observed. @LKM What middleware are you using? – Régis B. Aug 01 '16 at 05:59
  • B Thank you for replying. I'm really struggling with this issue in this link : http://stackoverflow.com/questions/38620296/django-authenticate-with-the-user-model-retrieved-by-the-foreign-model – LKM Aug 01 '16 at 09:31
  • I'm using : MIDDLEWARE_CLASSES in settings.py = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',] – LKM Aug 01 '16 at 09:32
  • It's not about Open edX and the related backend. It's about the code 'user.backend=None' – LKM Aug 01 '16 at 09:33
  • Ok let's move the conversation to the other question, which is in fact totally unrelated. (please delete your last two comments) – Régis B. Aug 01 '16 at 10:08