having trouble getting user authentication to work in Python - python

I am building a django/react app and having trouble with the backend user authentication, have not been able to debug the issue.
After successfully creating an account I am now trying to login. This is the the login route I have built.
#csrf_exempt
#api_view(['POST'])
def loginUser(request):
data = request.data
if request.method == 'POST':
email = data['email']
password = data['password']
try:
user = User.objects.get(email=email)
except:
message = {'detail': 'email does not match a user'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
username = user.username
user = authenticate(request, username=username, password=password)
# Returning correct username and password
print('This is the username:', username)
print('This is the password:', password)
# returning None, even though username and password are matching the info used for signup. (confirmed on admin page)
print('This is the user:', user)
if user is not None:
login(request, user)
serializer = UserSerializer(user, many=False)
message = {'detail': 'user has been logged in'}
return Response(serializer.data)
else:
message = {'detail': 'Username or password is incorrect'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
Any help would be greatly appreciate it since I have been stuck on this for 2 days.

It may be due to the Try-Except or due to the fact that you use email instead of username (but I dont think that matters). You could try something like this:
from django.contrib.auth import authenticate
from django.contrib.auth.models import auth
def loginUser(request):
if request.method == 'POST':
username = request.POST['name']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
auth.login(request, user)
return redirect('index')
else:
messages.info(request, 'Invalid Username or Password')
return redirect('login')
else:
return render(request, 'login.html')
Hopefully this helps.
If you use this code and the problem still persists, it could be that your template or urls may not be correct.

Related

How can I change django login form from username to email when users wanted to login

Is there anyways I can change django custom user login from Username to Email? I have try using this method but it does not work:
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = auth.authenticate(request, email=email, password=password)
if user is not None:
auth.login(request, user)
return redirect('Home')
else:
messages.info(request, 'Invalid Credential')
return redirect('login')
else:
return render(request, 'login.html')
I want to allow user to login using Email not Username.

Django differentiate between incorrect login information and inactive user on login

Currently I added in my site a method for email confirmation when registering. What I saw though, is that when the user is registered, but didn't click in the confirmation link yet and tries to login, I can't differentiate between wrong user/password and not confirmed user.
This is my login function:
def loginUser(request):
if request.user.is_authenticated:
return redirect("decks:index")
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(request, user)
return redirect("myApp:portal")
elif user is not None:
messages.error(request, "Email is not confirmed.")
else:
messages.error(request, "Invalid username or password.")
else:
messages.error(request, "Invalid username or password.")
form = AuthenticationForm()
return render(request, "myApp/login.html", context = {'login_form': form})
The problem is that when running form.is_valid() the authenticate function from /home/nowork/.local/lib/python3.8/site-packages/django/contrib/auth ModelBackend is executed:
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
try:
user = UserModel._default_manager.get_by_natural_key(username)
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a nonexistent user (#20760).
UserModel().set_password(password)
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
So the form.is_valid() will never be true when the is_active flag is False. So I have no way of telling if the combination of user+password is incorrect or the user is not confirmed yet.
I'm not sure what's the correct way of doing this, I thought to do something like:
User.objects.get(username=request.POST['username'])
Can users exploit this somehow? Is there any better way to accomplish this?
Using python3 and Django 4.0
You can make your own CustomLoginBackend as
from django.contrib.auth import get_user_model
class CustomLoginBackend(object):
def authenticate(self, request, username, password):
User = get_user_model()
try:
user = User.objects.using(db_name).get(username=username)
except User.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None
Then in your views.py
def loginUser(request):
if request.user.is_authenticated:
return redirect("decks:index")
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active == True:
login(request, user)
return redirect("myApp:portal")
else:
messages.error(request, "Email is not confirmed.")
else:
messages.error(request, "Invalid username or password.")
else:
messages.error(request, "Invalid username or password.")
form = AuthenticationForm()
return render(request, "myApp/login.html", context = {'login_form': form})
And at last don't forgot to add AUTHENTICATION_BACKENDS in your settings.py as
AUTHENTICATION_BACKENDS = ['path_to_your.CustomLoginBackend ',]

Django Authenticate always returns None with correct credentials also

I was creating a login and registration page for my project and was using the Django MySQL database for login and creating users the signup was done correctly but the login function is not working for me.
PS: The is_active is Set True but still this is not working
With all correct info, it shows None. I have given all the necessary parts of the file and codes
I tried everything but nothing seems to work also tried some of the solutions listed on StackOverflow but still, nothing worked for me.
from django.shortcuts import render, redirect
from .models import Description
from django.http import HttpResponse
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
# Create your views here.
def index(request):
d = Description.objects.all()
return render(request,'index.html',{'des':d})
def signup(request):
if request.method == 'POST':
first_name = request.POST['first']
last_name = request.POST['last']
user_name = request.POST['user']
email = request.POST['email']
pass1 = request.POST['password1']
pass2 = request.POST['password2']
if pass1 == pass2:
if User.objects.filter(email=email).exists():
print("Email taken")
elif User.objects.filter(username=user_name).exists():
print("Username taken")
else:
user = User.objects.create_user(username = user_name, first_name=first_name,last_name=last_name, password=pass1, email=email)
user.save()
print("User created")
else:
print("Password Not Matching")
return redirect('/')
else:
return render(request,'signup.html')
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
print(email,password)
user = authenticate(request, email=email, password=password)
print(user)
if user is not None:
login(request, user)
print("Logged in")
else:
print("not logged in")
return redirect('/')
else:
return HttpResponse("Invalid")
Django authenticate method allows for authenticating using only username.
You can get the user's username from the User model using the user's email
username = User.objects.get(email=email).username
password = request.POST.get('password')
Replace this user = authenticate(request, email=email, password=password)
with this user = authenticate(request, username=username, password=password)
The problem is django's default authentication mechanism don't allow you authenticate using email, you can only authenticate user using username .
either way, you can get the user's username from the User model using his email and then you can authenticate user.
def login(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
username = ''
try:
username = User.objects.get(email=email).username
except User.DoesNotExist:
return HttpResponse("Invalid")
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
print("Logged in")
else:
print("not logged in")
return redirect('/')
else:
return HttpResponse("Invalid")
Also dont store password directly, always user standard set_password() function of django
if User.objects.filter(email=email).exists():
print("Email taken")
elif User.objects.filter(username=user_name).exists():
print("Username taken")
else:
user = User.objects.create_user(username = user_name, first_name=first_name,last_name=last_name, email=email)
user.set_password(pass1)
user.save()
print("User created")
The problem is your signup method. You should not give password to the init function. You should use User's set_password method.
In your sign_up view remove password=pass1 at the line where you are creating User object. And after that before saving the user, add user.set_password(pass1).
Hope this helps!

Django Get None After User Authentication

def login_page(request):
form = LoginForm(request.POST or None)
context = {
"form" : form
}
print("User logged in")
print(request.user.is_authenticated())
if form.is_valid():
print(form.cleaned_data)
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(request, username = 'username', password = 'password')
print(user)
if user is not None:
print(request.user.is_authenticated())
login(request, user)
# Recirect to a success page.
# context['form'] = LoginForm()
return redirect("/contact")
else:
# Return an 'invalid login' error message.
print("Error")
return render(request, "auth/login.html", context)
I try to create a login page but I get value of 'user' None so I took error everytime. I use Django 1.11.
You are trying to authenticate with constant credentials but need to authenticate with data from form.
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(request, username=username, password=password)
# ^ ^
# changed from 'username' and 'password' to variables
If your user provided wrong credentials, then authenticate return None, since no user can be authenticated with those.

MultiValueDictKeyError at /login/ "u'username'"

I am trying to build a web api for a login page. I keep getting this error. Although i have seen similar and related issues online, the solutions have been of help to me. What am i not doing right?
error
MultiValueDictKeyError at /login/
"u'username'"
login
#csrf_exempt
def my_view(request):
user = request.POST['username']
passcode = request.POST['password']
user = authenticate(request, username=user, password = passcode)
if user is not None:
login(request, user)
return HttpResponse("User logged in")
else:
return HttpResponse("User not found")
updated login
#csrf_exempt
def my_view(request):
if request.method == 'POST':
user = request.POST['username']
passcode = request.POST['password']
user = authenticate(request, username=user, password = passcode)
if user is not None:
login(request, user)
return HttpResponse("User logged in")
else:
return HttpResponse("User not found")
Remove the request parameter from authenticate function,
user = authenticate (username=username, password=passcode)
Edit your view,
#csrf_exempt
def my_view(request):
user = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return HttpResponse("User logged in")
else:
return HttpResponse("User not found")
I just use the request.POST.get('your field_name here')
for example use username = request.POST.get('username') to pick your username

Categories

Resources