Django authenticate method returns None - django

I am trying to create a user login. I am registering the user through django's admin page. Username and passwords are entered correctly.
Also I have tried adding authentication backends to settings.py
I have tried multiple ways but couldn't get it to work.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
My code looks like below :
models.py :
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
views.py:
def login(request):
if request.method == 'POST':
username = request.POST.get('user')
password = request.POST.get('pass')
user = authenticate(username=username,
password=password) ----------> None
if user:
if user.is_active():
login(request, user)
return HttpResponseRedirect(reverse('index'))
else:
return HttpResponse('Account not active')
else:
print('Someone tried to login and failed ')
print('Username {} and passowrd {}'.format(username, password))
return HttpResponse('Invalid login details supplied!!')
else:
return render(request,'account/login.html', {})

The username and password from the below ones are coming as empty so it is giving none
username = request.POST.get('user')
password = request.POST.get('pass')
Try to inspect the element from HTML to find the name of the fields from which the data is coming from the template or print the values of username and password variables to cross verify.
use request.POST.get('username'), request.POST.get('password1') but as told it totally depends on the html template. It is safer to clean the data and then go for authentication.
Django has inbuilt Class Based Views for the same purpose. Give them a try

Related

How to update User password in django

I'm having trouble when i try to update user password in django.
def password(request):
if request.method=="POST":
password =request.user.password
username=request.user.username
c_password=request.POST["current_password"]
new_password=request.POST["new_password"]
r_new_password=request.POST["retype_new_password"]
if password==c_password:
if new_password==r_new_password:
user =User.objects.get(username=username)
user.set_password(new_password)
user.save()
messages.info(request,"Successfully saved")
else:
messages.info(request,"PASSWORD DOES NOT MATCH")
else:
messages.info(request,"PASSWORD INCORRECT")
return render(request,"security.html")
When i fill the current password, it is giving me error password incorrect. But, when i fill pbkdf2_sha256$320000$Cb4s4nwqKwirdgo50ZdjLH$aeuSP3X+dSZXsv0XJB0XxkpwfsmU+PedMX9Jl50Zark=
, my password becomes correct and user password is updateable. My problem is I would like to fill in current password field as normal current password without getting the error.
You use authenticate(…) [Django-doc] to validate the password: this will retrieve the hashing algorithm and the salt, and check if the hashes match, so you can work with:
def password(request):
if request.method == 'POST':
c_password = request.POST['current_password']
new_password = request.POST['new_password']
r_new_password = request.POST['retype_new_password']
user = authenticate(username=request.user.username, password=c_password)
if user is not None:
if new_password == r_new_password:
user.set_password(new_password)
user.save()
messages.info(request, 'Successfully saved')
else:
messages.info(request, 'PASSWORDS DOE NOT MATCH')
else:
messages.info(request, 'PASSWORD INCORRECT')
return render(request, 'security.html')
There is however a PasswordChangeView [Django-doc] to change the password: this already implements the logic and uses a form. You can inject a different template, for example with:
path(
'password/change/',
PasswordChangeView.as_view(template_name='security.html'),
name='password_change'
)
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
Note: It is better to use a Form [Django-doc]
than to perform manual validation and cleaning of the data. A Form will not
only simplify rendering a form in HTML, but it also makes it more convenient
to validate the input, and clean the data to a more convenient type.
Refer the Documentation Django does not store raw (plain text) passwords on the user model
use authenticate function instead of using if password==c_password:.
from django.contrib.auth import authenticate
def password(request):
if request.method=="POST":
password =request.user.password
username=request.user.username
c_password=request.POST["current_password"]
new_password=request.POST["new_password"]
r_new_password=request.POST["retype_new_password"]
user = authenticate(username=username, password=c_password)
if user is not None:
if new_password==r_new_password:
user =User.objects.get(username=username)
user.set_password(new_password)
user.save()
messages.info(request,"Successfully saved")
else:
messages.info(request,"PASSWORD DOES NOT MATCH")
else:
messages.info(request,"PASSWORD INCORRECT")
return render(request,"security.html")

How to use check_password function in django

I'm a beginner in Django. I have a signup form with only 2 fields. Username and Password. The password is encrypted using the pbkdf2_sha256 algorithm.
I want to login using the username and password.so the password that I'm inputting in the login page must be checked with the encrypted password. How to do that?. Also, please explain what authenticate and check_password function does?
def save(request):
if request.method == 'POST':
name = request.POST.get('name')
password = request.POST.get('pass')
enc_pass = pbkdf2_sha256.encrypt(password,rounds=12000,salt_size = 32)
a = signup(username = name, password = enc_pass)
a.save()
return render(request,'save.html')
def login(request):
if request.method == 'POST':
username = request.POST.get('user')
password1 = request.POST.get('password1')
p = check_password(password=password1)
if signup.objects.filter(username__exact=username).exists() and p is True:
return HttpResponse("Success")
else:
return HttpResponse("Invalid Credentials")
return render(request, 'login.html')
You can do:
if check_password(password_user_entered, request.user.password):
# You can authenticate
Here, password_user_entered is password that came from the request(or, pw to be checked). And, request.user.password which is the password with which we want to compare.
check_password does not work like this. To make it work, you need to use Django's own authentication system. If you are concerned about using pbkdf2_sha256, Django provides this hasher. To use this with you own auth system, add it to settings:
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.Argon2PasswordHasher',
]
And in django authentication, you do not need to hash it manually, django will take care of it itself. All you need to do is save the user like this:
from django.contrib.auth.models import User
user = User.objects.create_user(username=username, email=email, password=password, #.. other required fields)
And to check password:
user = User.objects.get(username=username)
user.check_password(password)
More information can be found in documentation

Authenticating a User, without using Django rest framework?

Hey everyone I have a couple questions in regards to refactoring some old api endpoints as far as authentication goes. I have a view for example...
#csrf_exempt
# PARAMETERS: username, password
def submit_offer(request):
"""Submit an offer"""
username = request.GET.get("username")
password = request.GET.get("password")
# Authenticate user to set instance.user value into BuyerForm
user = authenticate(username=username, password=password)
if not user:
# Always want our potential Buyer to be logged in & authenticated
return JsonResponse({'message': 'Please login to continue.'})
if request.method == 'POST':
form = BuyerForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
# sets current user as Buyer.user
instance.user = user
instance.save()
return JsonResponse({'success': True}, status=200)
else:
data = form.errors.as_json()
return JsonResponse(data, status=400, safe=False)
else:
return JsonResponse(data={'status': 403})
Now every view that uses a form, and needs to grab the instance.user, has the same lines of code below...now I thought using request.user would do the job, but when testing that way I am getting back an AnonymousUser, which is kind of confusing me?
username = request.GET.get("username")
password = request.GET.get("password")
# Authenticate user to set instance.user value into BuyerForm
user = authenticate(username=username, password=password)
Now is there a better way to authenticate the user, like in a regular django view using request.user, rather than having to manually authenticate the user in each view? (edited)
password = request.GET.get("password").
This is very vulnerable way to design a django app.
Please see
Accessing Username and Password in django request header returns None
BTW, write a custom middle ware and put your code there.
username = get_username_from_header
password = get_password_from_header
# Authenticate user to set instance.user value into BuyerForm
user = authenticate(username=username, password=password)
# Attach user to request
request.user = user
As each request are being passed through the middle-ware, you can access the user from each view.

#login_required not working as expected in Django?

I find #login_required very useful. I have used this #login_required(login_url='/login/') before each views. If the user tries to access /upload url it redirects to url as: http://127.0.0.1:8000/login/?next=/upload_file/ My urls are very simple:
urlpatterns = patterns('',
#url(r'^admin/', include(admin.site.urls)),
url(r'^upload_file/', 'fileupload.views.upload_file'),
url(r'^show_file/', 'fileupload.views.show_list'),
url(r'^sync/', 'fileupload.views.sync'),
url(r'^login/', 'fileupload.views.login_user'),
url(r'^upload_file_form', 'fileupload.views.upload_file_form' )
)
Now when the user presses login the page is redirected to nowhere. I am sure my url pattern is not correct. What am I missing? Thanks
Edit:
def login_user(request):
errors = []
state = "LOG IN"
username = password = ''
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(username='username', password='password')
if user is not None:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
else:
state = "Your account is not active, please contact the site admin."
else:
state = "Your username and/or password were incorrect."
return render_to_response('login.html', {'state':state, 'username': username}, context_instance=RequestContext(request))
Your fileupload.views.login_user view needs to honor the next querystring parameter itself. This is built-in to Django's login view, but since you have rolled your own, you'll need to implement that functionality yourself.

want to improve my view

I've view like this. It worked. I'm new to django. Can you please help me to improve this code? thank you
def getAPI(request):
username = request.GET.get('username')
password = request.GET.get('password')
#TODO Match user and password
if username:
user = User.objects.get(username__exact=username)
is_exist = user.check_password(password)
if is_exist == True:
api_key = ApiKey.objects.get(id=user.id)
else:
error_message = 'username or password is invalid.'
return render_to_response('details.html',locals(),
context_instance=RequestContext(request)
)
if username and password does not exist Then I want to print error message. Otherwise I want to print ApiKey. thanks
Do you mean "print" (in which case just use python's print function) or do you want to return it in the response? If the latter, read up about django templates and passing variables to render_to_response.
Also, sticking a password as a GET variable is a bit of a bad idea, since it'll be visible on the URL:
http://example.com/whatever?username=me&password=s3cr3t
User/pass info should normally be sent via POST from a form. But maybe you're not that bothered about security.
Here's the basic template to authenticate a user:
from django.contrib.auth import authenticate
def my_view(request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
# User is authenticated - return api key
else:
# Return a 'disabled account' error message
else:
# Return an 'invalid login' error message.