Django urlsafe_base64_decode returns None - django

So I'm making an email verification system but urlsafe_base64_decode is returning None instead of the pk.
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
subject = 'Activá tu mail'
current_site = get_current_site(request)
encoded_uid = urlsafe_base64_encode(force_bytes(user.pk)).decode()
message = render_to_string('firstpage/acc_active_email.html', {
'user': user,
'domain': current_site.domain,
'uid': encoded_uid,
'token': account_activation_token.make_token(user),
})
to_email = form.cleaned_data['email']
from_email = 'backend_email#gmail.com'
send_mail(subject, message, from_email, [to_email])
user.set_password(password)
user.save()
user_profile=UserProfile.objects.create(user=user)
#returns user objects if credentials are correct
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('/')
return render(request, self.template_name, {'form': form})
Then the users clicks on a link and this is redirected to this function
def activate(request, uidb64=None, token=None):
uid = urlsafe_base64_decode(uidb64).decode()
user = User.objects.get(pk=uid)
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.save()
login(request, user)
# return redirect('home')
return HttpResponse('Thank you for your email confirmation. Now you can login your account.')
else:
print(user)
print(uid)
print(account_activation_token.check_token(user, token))
return HttpResponse('Activation link is invalid!')
uidb64 returns the same as urlsafe_base64_encode(force_bytes(user.pk)).decode() but urlsafe_base64_decode(uidb64).decode() returns None.
I'm using Django 2.1 by the way.

You need to use force_text to return a str object representing arbitrary object and keep the lazy objects, use this - force_text(urlsafe_base64_decode(uidb64))
For more reference you can visit the documentation
-https://docs.djangoproject.com/en/2.1/ref/utils/#django.utils.encoding.force_text
Hope this will help you.

This is very late. But for anyone like me that stumbles upon this and has the exact same problem.
Django 3 >>
The problem is on this line
'token': account_activation_token.make_token(user),
And the reason is because the user given here is a form instead of a proper user instance.
Therefore, for solution:
user_instance = request.user # if the user is logged in or
user_instance = get_user_model() # if you're using default user model or
user_instance = YourUserModel # if you are using a custom user model
Then:
'token': account_activation_token.make_token(user_instance),

Related

How can I decode a token sent to a user to know when it was created

Hello I did a reset password system in my web that sends a token link to the client's mail in order to client can reset the password, And I want to check the timestap of the hashed token, to make some condition like... expire in 24h.
This file makes the token and I "guess" is hashing user.pk and timestap and returning a hashed token. I want to make reverse process to know when that token was created.
tokens.py:
from django.contrib.auth.tokens import PasswordResetTokenGenerator
import six
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.pk) + six.text_type(timestamp)
)
account_activation_token = AccountActivationTokenGenerator()
Token link is going perfect and client can change the passord whitn no problems.
this is my view that handle this with 2 functions 1st for sending the mail, and 2nd for reset the password.
views.py:
def reset_password(request):
form = ResetPasswordForm(request.POST or None)
if form.is_valid():
user = User.objects.filter(email=form.cleaned_data.get('email'))
if not user:
messages.error(request,'This user does not exist')
else:
user = user.first()
current_site = get_current_site(request)
subject = 'Reset Password'
message = render_to_string('core/reset_password_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
send_mail(subject,message,conf_settings.EMAIL_HOST_USER,[user.email,])
messages.success(request,'Password reset link sent to your email')
return redirect('consumer:consumer_home')
context = {
'form':form,
}
return render(request,'core/password_reset.html',context)
def reset_password_confirm(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
form = ResetPasswordConfirmationForm(request.POST or None)
if form.is_valid():
password = form.cleaned_data.get('password1')
user.set_password(password)
user.save()
login(request,user)
messages.success(request,'Password changed!')
return redirect('consumer:consumer_home')
context = {
'form':form,
}
return render(request,'core/password_reset_confirmation.html',context)
Now I have no clue to how to decode client token in order to extract the timestap that I hashed when I sent it in the first place.
From what I gather, you can update your AccountActivationTokenGenerator to include a timestamp:
class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.pk) + six.text_type(timestamp) + six.text_type(time.time())
)
You can then create a function to check the token when confirming the reset:
def reset_password_confirm(request, uidb64, token):
def check_token(token):
try:
user_id, timestamp, creation_time = token.split(":")
user = User.objects.get(pk=user_id)
if account_activation_token._make_hash_value(user, timestamp) != token:
return False
return user, creation_time
except Exception:
return False
try:
uid = force_text(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
result = check_token(token)
if user is not None and result:
user, creation_time = result
form = ResetPasswordConfirmationForm(request.POST or None)
if form.is_valid():
password = form.cleaned_data.get("password1")
user.set_password(password)
user.save()
login(request, user)
messages.success(request, "Password changed!")
return redirect("consumer:consumer_home")
context = {'form':form,}
return render(request, "core/password_reset_confirmation.html", context)
You'll then have access to creation_time which you can use in template through context.

Why django form valdation error does not work in my form

I want to show user validation error but seems that this is not working in my login form here is the code
my forms.py
class LoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput())
password = forms.CharField(widget=forms.PasswordInput())
remember_me = forms.BooleanField(required=False, label='Remember Me',help_text='Keep me logged in.',widget=forms.CheckboxInput())
def clean(self, *args, **kwargs):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError("This user doesn't exist")
if not user.check_password(password):
raise forms.ValidationError("Incorrect Password")
if not user.is_active:
raise forms.ValidationError("User no longer Active")
return super(LoginForm,self).clean(*args,**kwargs)
my views.py for login
def my_login(request):
if 'next' in request.GET:
messages.add_message(request, messages.WARNING, 'To Continue, Please login here!')
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
remember_me = form.cleaned_data['remember_me']
user = authenticate(username=username, password=password)
if user:
login(request, user)
if not remember_me:
request.session.set_expiry(0)
return redirect('accounts:home')
else:
request.session.set_expiry(1209600)
return redirect('accounts:home')
else:
messages.info(request, 'Please check your credentials.')
return redirect('accounts:login')
else:
form = LoginForm()
return render(request, "login.html", {'form': form})
i know i am redirecting the form if form credential is wrong but if i don't i will throw error didn't return a httpresponse it return none instead also want to what is the best way to redirect or show exact validation error of which credential is wrong

Django Login Authentication: I am able to SignUp new user and create new user as well but UNABLE to login as SignUp user

I'm able to SignUp new user as well but UNABLE to login for handlelogin
def handlelogin(request):
if request.method == 'POST':
loginemail= request.POST['loginemail']
loginpass = request.POST['loginpass']
user = authenticate(request, username=loginemail, password=loginpass)
if user is not None:
print(loginemail, loginpass)
login(request, user)
messages.success(request, "Successfullly Logged-In")
return redirect('/')
else:
messages.error(request, "Invalid Credentials, Please Try Again")
return redirect('/')
return HttpResponse('404 - Page Not Find')
I have tried print() statement to check and it do work in else statement only, not in if user is not none.
NOTE: THE SYNTAX IN QUESTION IS LITTLE BIT DISTURBED... BUT IN CODE IT IS COMPLTELY FINE.
BTW I use Django forms for login and logout users:
views.py:
def user_login(request):
if request.method == 'POST':
form = UserLoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(request, username=cd['username'], password=cd['password'])
if user is not None:
login(request, user)
messages.success(request, 'you logged in successfully', 'success')
return HttpResponseRedirect('dashboard/')
else:
messages.error(request, 'username or password is wrong', 'danger')
else:
form = UserLoginForm()
return render(request, 'login.html', {'form': form})
def user_logout(request):
logout(request)
messages.success(request, 'you logged out successfully', 'success')
return HttpResponseRedirect('')
forms.py
class UserLoginForm(forms.Form):
username = forms.CharField(max_length=30)
password = forms.CharField(max_length=50)
urls.py
urlpatterns = [
path('', user_login),
path('logout/', user_logout, name='user_logout'),
]
Also if you haven't make sign Up page you should make user manually by python3 manage.py createsuperuser command.
For sign Up page:
urls.py
urlpatterns = [
...
path('signup/', signup, name='signup'),
]
views.py
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('home')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
forms.py
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')

want to remove error message in custom login form in django custom login

i don't want user have to see this message without any error i load page this come automatically here is my views.py
def my_login(request):
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('accounts:home')
else:
return HttpResponse('<h1>Page was found</h1>')
else:
return render(request, "login.html", {'form': form})
my forms.py
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
def clean(self, *args, **kwargs):
username = self.cleaned_data.get("username")
password = self.cleaned_data.get("password")
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError("User does not exist.")
if not user.is_active:
raise forms.ValidationError("User is no longer active.")
return super(LoginForm, self).clean(*args, **kwargs)
You need to submit your form only when you receive a POST request.
def my_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
# process form here
else:
form = LoginForm()
# send form to template
You will find more info about this in the documentation.

Getting error 'django.contrib.auth.models.User.DoesNotExist: User matching query does not exist'

A similar question has been asked before but after going through all of them I was not able to find any answer to fit my case.
I am using Django's built-in authentication system to authenticate and log in a user. The user uses a log in form on index form and is supposed to be then redirected to a different url.
However after I log in with a username and password that are both valid entries, I am not redirected to the next url as I should be, and I get this error:
django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.
These are my import lines for authenticate, login, and then for User.
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
But I don't think the problem is there.
It can't find the user but I don't know why that could be, because I am creating a username in the form and a password so it should be present.
Here is my login code:
def index(request):
if request.method == 'POST':
print("Received POST")
form = LoginForm(request.POST)
if form.is_valid():
print("FORM is Valid")
# proceed with registration
username, pwd = request.POST.get("username", None), request.POST.get("password", None)
if not username or not pwd:
print("nobody around here")
return HttpResponse("Username or password not present")
user = User.objects.get(username=username)
if user:
user = authenticate(username=username, password=pwd)
else:
user = User.objects.create_user(username, username, pwd)
login(request, user)
return redirect("dashboard")
else:
print("FORM is NOT VALID")
template = loader.get_template('index.html')
context = {
'username': 'Ralf',
'form': form,
}
return HttpResponse(template.render(context, request=request))
else:
# load the template file
template = loader.get_template('index.html')
context = {
'username': 'Ralf',
'form': LoginForm(),
}
return HttpResponse(template.render(context, request=request))
EDIT: I tried using a try except block and now the page will not load the form:
Here is the code I used:
if form.is_valid():
print("FORM is Valid")
# proceed with registration
username, pwd = request.POST.get("username", None), request.POST.get("password", None)
if not username or not pwd:
print("nobody around here")
return HttpResponse("Username or password not present")
try:
user = User.objects.get(username=username)
user = authenticate(username=username, password=pwd)
except:
user = User.objects.create_user(username, username, pwd)
login(request, user)
return redirect("dashboard")