authenticate of django doesnt work - django

I am working on a password reset for django, but whatever I try the reset doesn't work. So i checked what my form handled on data which i knew had to be true. It still didn't work. So alst i tried to authenticate in the django shell. and this is what happened.
shell:
In [11]: user = User.objects.first()
In [12]: password = "bier"
In [13]: user.set_password(password)
In [14]: i = authenticate(username=user.username, password=password)
In [15]: i
i returns None
Someone any clue about what is causing this?

You should save your user object,
user.save()
According to the docs, user object is not saved:
"Sets the user’s password to the given raw string, taking care of the password hashing. Doesn’t save the User object."
https://docs.djangoproject.com/en/1.8/ref/contrib/auth/#django.contrib.auth.models.User.set_password

from django.contrib.auth.models import User
u = User.objects.get(username='john')
u.set_password('new password')
u.save()
https://docs.djangoproject.com/en/dev/topics/auth/default/#changing-passwords
https://docs.djangoproject.com/en/dev/topics/auth/default/#authenticating-users

Related

Can not login as superuser in DRF

Created superuser several times with this credentials.
username: admin
password: root
Did it with terminal and with Djnago ORM. Same result.
>>> from bank.models import User
>>> User.objects.create_superuser(username="admin", password="root")
>>> from django.contrib.auth import authenticate
>>> u = authenticate(username="admin", password="root")
>>> u
>>> type(u)
<class 'NoneType'>
>>> admin = User.objects.get(username="admin")
>>> admin
<User: admin>
>>> admin.is_active
True
>>> admin.is_staff
True
>>> admin.is_superuser
True
It's started since I started using python-jwt tokens, but it fails before code goes to token part.
Same login function as normal user works as it supposed to be and gives working token.
#api_view(['POST'])
def login_view(request):
username = request.data.get("username")
password = request.data.get("password")
user = User.objects.filter(username=username).first()
if user is None:
raise exceptions.AuthenticationFailed("Invalid Credentials")
if not user.check_password(password):
# code fails here after trying lo log in as superuser
raise exceptions.AuthenticationFailed("Invalid Credentials")
token = services.create_token(user_id=user.id)
resp = response.Response()
resp.set_cookie(key="jwt", value=token, httponly=True)
resp.data = {"token": token}
return resp
It happens because of UserManager. Default Django UserManager hashes password when creates superuser. When you try to create normal user, by default its password doesn't get hashed.
In my case I hashed password by rewriting save() method in User model.
def save(self, *args, **kwargs):
self.set_password(self.password)
super().save(*args, **kwargs)
And it works perfectly for normal user, but superuser's password hashes by itself, so because of this method it hashes twice. So password check looked something like \
hash(input_password) == hash(hash(original_password))
That's why I could not login as superuser.
UPD: just create user with User.objects.create_user(**data). It hashes password automatically. In that case you do not even need to rewrite save() method in User model.

password dont change in views.py on django

I'm trying to change a user's password on my views.py and whenever I change the password, I lose my connection and access to my account
my view.py:
user = User.objects.get(id=request.user.id)
user.password = make_password(request.POST.get("password"))
user.save()
A User object normally has a .set_password(…) method [Django-doc], so you can update that password with:
request.user.set_password(request.POST['password'])
request.user.save()
You can omit fetching the user object, since request.user aleady does that. Using user = User.objects.get(id=request.user.id) is thus an extra query that only is equivalent to request.user.
try using set_password instead of make_password like that
user = User.objects.get(id=request.user.id)
user.password = set_password(request.POST.get("password"))
user.save()
The following is an explanation provided by the Django documentation https://docs.djangoproject.com/en/3.2/topics/auth/default/#changing-passwords

Django - Authenticate with custom User model returns None

I'm following a tutorial (https://thinkster.io/tutorials/django-json-api/authentication) on setting up authentication. I've got to the point where I'm registering users and receiving the tokens back. I can drop into the shell and do;
>>> user = Users.objects.first()
>>> user.email
>>> test#outlook.com
>>> user.password
>>> 12345678
This shows that the user exists in the database. But when calling my login endpoint;
/users/login/
the authenticate method returns None.
user = authenticate(username=email, password=password)
I'm printing the email and password just before and it shows the correct data passed in.
I've also set my USERNAME_FIELD to email in my model.
USERNAME_FIELD = 'email'
I've updated my model in my settings to be
AUTH_USER_MODEL = 'aemauthentication.User'
I've had a look around and the above line in the settings file seems to be the approved answer for most people with this issue.
GitHub link to project - https://github.com/Daniel-sims/aem_1
As per; Django User Creation successful, but authenticate() returning None
I'd changed the create_user method to take the password as a parameter;
user = self.model(username=username, email=self.normalize_email(email), password=password)
but you have to call set password, so everythings working fine with;
user = self.model(username=username, email=self.normalize_email(email))
user.set_password(password)

Django: How to delete token after it is used?

In Django, I am generating tokens for account activation. Here is the actual code:
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': default_token_generator.make_token(user),
For instance:
http://localhost:8000/reset/MjQ/4uf-785b6e83f11ac22b6943/
In the above url MjQ is uid and 4uf-785b6e83f11ac22b6943 is token.
The account activation code goes like this:
def activate_account(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = get_user_model().objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if (user is not None and default_token_generator.check_token(user, token)):
user.is_active = True
user.save()
messages.add_message(request, messages.INFO, 'Account activated. Please login.')
return redirect('login')
The problem is once it is used it is still valid. However, Django password reset mechanism (password_reset_confirm() view) somehow invalidates the token after it is used. How can I do the same?
The token is not stored. It is a hash value based on:
the user's password
the user's last login date
Thus when Django's password reset confirm actually changes the password, the token hash is automatically invalidated.
If you want to manually invalidate the hash, you can do so by either:
generate and store a random password for that user (this may not be
what you want if you to retain the user's previous password):
password = User.objects.make_random_password()
user.set_password(password)
or reset the user's last login date to the current timestamp
from django.utils import timezone
user.last_login = timezone.now()
Why taking care of deleting stuff? It is much better to use something what expires automatically after some time.
See django.core.signing.TimestampSigner
https://docs.djangoproject.com/en/2.0/topics/signing/#verifying-timestamped-values
for nice how-to see this page I will only extend it by wrapping the generated key in base64.urlsafe_b64encode(...) and then before unsigning base64.urlsafe_b64decode(...)

Login fails with user from data migration

I try to add a new user with help of data migration (django 1.6.7 + south). My migration:
class Migration(DataMigration):
def forwards(self, orm):
user = User(
pk=1,
username="admin",
password="admin",
is_active=True,
is_superuser=True,
is_staff=True,
last_login="2011-09-01T13:20:30+03:00",
email="email#gmail.com",
date_joined="2011-09-01T13:20:30+03:00"
)
user.save()
def backwards(self, orm):
raise RuntimeError("Cannot reverse this migration.")
User creation works as I'm able to obtain the user instance via the shell:
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(pk=1)
>>> user.username
u'admin'
>>> user.password
u'admin'
The problem is when I'm trying to authorise via the admin panel, there is an error:
Please enter the correct username and password for a staff account. Note that both fields may be case-sensitive.
You can't add a password in this way for a User object (i.e. password="admin"). When Django authenticates a user it hashes the password you enter in the admin login screen using your settings.SECRET_KEY. When Django attempts to match this hash against your stored password, it is matching against the string 'admin'.
You need to update your migration to look like the following:
user = User(pk=1, username="admin", is_active=True,
is_superuser=True, is_staff=True,
last_login="2011-09-01T13:20:30+03:00"
email="email#gmail.com",
date_joined="2011-09-01T13:20:30+03:00")
user.set_password('admin')
user.save()
Note the removal of the password='admin' and the addition of the useful User model method set_password
HTH
The call to user.set_password(), as suggested in this other answer, fails in my data-migration (django 2.1) with the following error:
AttributeError: type object 'User' has no attribute 'set_password'
A similar issue is discussed in this bug report. As suggested there, you can use make_password() instead (also see docs):
from django.contrib.auth.hashers import make_password
def create_user(app_registry, schema_editor):
user_model = app_registry.get_model(settings.AUTH_USER_MODEL)
user_model.objects.create(username='a. user',
email='a.user#email.com',
password=make_password('areallystrongpassword'))