3

My primary requirement is to have Email authentication. Though my custom authentication backend seems to work fine, user.is_anoynymous() function is still True even after succesfully authenticating with my custom backend. When using the default authentication model everything seems fine.

views.py:

 from testapp.models import *
 from django.http import HttpResponseRedirect,HttpResponse,Http404,QueryDict
 from django.shortcuts import    render_to_response,  RequestContext         
from django.template import Context
from django.core.paginator import Paginator,QuerySetPaginator
from django.template.loader import get_template
from django.contrib.auth   import    logout,authenticate,login
from django.contrib.auth.views import *
from testapp.forms import *
from django.contrib.auth.decorators import login_required
from django.views.generic import ListView
from testapp.backends import EmailBackend
from testapp.backends import EmailBackend

def main_page(request):
    return render_to_response('main_page.html',{
        'user':request.user
    })

def loggedout(request):
    logout(request)
    return HttpResponseRedirect('/')

def custom_login(request):
    if request.method == 'POST':
        form = LoginForm(request.POST)
    if form.is_valid():
        email = request.POST['email']
        password =  request.POST['password1']

        cb = EmailBackend()
        user = cb.authenticate(email,password)
        # return HttpResponse(user.username)
        if user is not None:
            if user.is_active:
                login(request,user)
                return HttpResponseRedirect('/')
            else:
                return HttpResponse('USer is not Active')
        else:
            return HttpResponse('USer Not found')
else:
    form = LoginForm()
    page_var = RequestContext(request, {
        'form':form, 
    })
    return render_to_response('customlogin.html',page_var)`

backends.py:

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

class EmailBackend(ModelBackend):

    def authenticate(self,email= None,password= None):
        try:
            user = User.objects.get(email=email)

            if user is not None:
                if user.check_password(password):
                    return user
                else :
                    return None
            else:
                return None
        except User.DoesNotExist:
            return None

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

settings.py:

AUTHENTICATION_BACKENDS = ('testapp.backends.EmailBackend','django.contrib.auth.backends.ModelBackend')

main_page.html:

{% extends "base.html" %}
{% block title %}Welcome to Django Bookmarks{% endblock %}
{% block head %}Welcome to Django Bookmarks{% endblock %}
{% block content %}
{% block customadd %}
    kskdsdsdl;sd
    {% endblock %}
{% if user.username %}
<p>Welcome {{ user.username }}!
Here you can store and share bookmarks!</p>
{% else %}
<p>Welcome anonymous user!
You need to <a href="/login/">login</a>.</p>
{% endif %}
{% endblock %}

Now although the main_page.html is called after successfully authentication, In main page {{user.username}} is always None and hence main_page.html opens as anonymous user.

user.is_anonymous() in main_page function in view.py returns True. What mistake am I making? After redirect to main_page.html I should see the user as logged in.

Edit 1: Last time I purposefully didn't put all the packages I included in views.py so I updated it now.

2 Answers 2

1

Django provides a login view. I recommend that you use this rather than writing your own.

If you use the Django login view, Django will use your authentication backend, because you have added it to the AUTHENTICATION_BACKENDS setting.

You would need to make a small change to the backend - change the field name from email to username so that it matches the login form. You would still filter the user based on their email.

def authenticate(self, username=None, password= None):
    try:
        user = User.objects.get(email=username)

If you continue to use your own login view, I can see a couple of possible issues. Firstly, you should import the authenticate method, and call that instead of instantiating your login backend.

from django.contrib.auth import authenticate

def custom_login(request):
    ...
    user = authenticate(email=email, password=password)
    ...

Secondly, when you call login(request, user), make sure you have imported the correct login method, and not the login view I mentioned above.

from django.contrib.auth import login
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the answer Alasdair. I purposefully didn't put all the packages I included in views.py ,Now I updated it .So I dont think there is an Import error.
Moreover cb.authenticate(email=email,password=password) works fine as I get the correct username if I return a HttpResponse(user.username) which I have hashed here. I think the issue is with the login(request,user) function and something to do with sessions not getting stored.
You have from django.contrib.auth.views import *, which is replacing the login method login with the login view login.
Even if calling cb.authenticate works, I recommend that you call authenticate. If you do things differently than recommended, then you're more likely to hit weird bugs that can be hard to fix.
Thanks mate that was the problem. login function was getting overwritten by login view.
0

Sorry, I don't see anything obviously wrong in your code. I'd recommend using Python's logging to aid in troubleshooting this.

Based on my own painful experience using email for authentication, you'll want to match case-insensitively because a lot of people will enter [email protected]. :)

user = User.objects.get(email__iexact=email)

...or only store lowercase email addresses. One project I worked on ended up with duplicate entries due to this.

Also, if that query succeeds, user will never be None, so you can skip that test and simplify your try-except block:

try:
    user = User.objects.get(email__iexact=email)
    if user.check_password(password):
        return user
    else:
        logger.debug('password check failed')

except User.DoesNotExist:
    logger.debug('user does not exist')

return None

1 Comment

Thanks for the answer Thomas. If you look at my views.py , after the line:- cb=authenticate(email=email,password=password) , i have a hashed an HtppResponse with username. when i uncomment that , I can see the correct user name returned as the response. So I don't think lowercase is the issue. The problem is, I am authenticated in the login function but that does not hold while I am redirecting to a new page. Do you think I have to write a custom login(request) function too? I am suspecting it has someting to do with my session not holding on?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.