0
votes

Client access the login view,

//user is properly set here  
user = auth.authenticate(username=email, password=password)  
auth.login(request,user)  

The same client which requested the login view, requests another view

// I expect the same user I logged in previously here. But I see anonymous user here.   
user = request.user

I don't know how exactly web server recognizes two different http requests (because http is connectionless) are coming from the same user. But I know that session is the concept that makes it possible.

I have MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware',...) in my settings.py

Is there something else I need to check to make this work?

-edit

I debugged a bit,
django/contrib/auth/init:login does request.session[SESSION_KEY] = user.id django/contrib/auth/init:get_user tries looking up request.session[SESSION_KEY] on next run and fails.

I need to understand what request.session is.
I thought request is something a client sends per http-request.(so it's not persistent)

** Below is my understanding, please correct me if I'm wrong **

  1. When a user logins, server assigns a unique id for a user and send it to the user.
  2. Server also stores relevant data for the id in somewhere persistent.
  3. The user sends the unique id for every subsequent http-request.(this is cookie)
  4. Django looks up data stored in step 2(or in other cases) with the id given.
  5. Django puts the data in request.session and give to view.

I followed Django, request.user is always Anonymous User

I suspect all this is due to my custom authentication backends copied from http://www.micahcarrick.com/django-email-authentication.html

My First View.

@csrf_exempt
def login(request):
    # import pdb                                                                                                                                                                                                                                                                
    # pdb.set_trace()                                                                                                                                                                                                                                                           

    email = request.POST['email']
    password = request.POST['password']

    user = auth.authenticate(username=email, password=password)
    # auth.logout(request)                                                                                                                                                                                                                                                      

    if user is not None and user.is_active:
        auth.login(request, user)

        profile = user.get_profile()
        user_dict = profile.to_dict()

        jsonUser = json.dumps(user_dict, ensure_ascii=False, cls=DjangoJSONEncoder)
        return HttpResponse(jsonUser)
    else:
        raise Http404

My second view.

@csrf_exempt
def user_update(request):
    import pdb
    pdb.set_trace()

    user = request.user

=>  if not user.is_authenticated():
        raise Http404  // always ends up here

    print 'in user_update'
.......

MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware', )

my Backends

from django.contrib.auth.models import User, check_password

class EmailAuthBackend(object):
    """                                                                                                                                                                                                                                                                         
    Email Authentication Backend                                                                                                                                                                                                                                                

    Allows a user to sign in using an email/password pair rather than                                                                                                                                                                                                           
    a username/password pair.                                                                                                                                                                                                                                                   
    """

    supports_inactive_user = False

    def authenticate(self, username=None, password=None):
        """ Authenticate a user based on email address as the user name. """
        try:
            user = User.objects.get(email=username)
            if user.check_password(password):
                return user
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        """ Get a User object from the user_id. """
        print 'getting an user for user_id: ', user_id
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
1
You should show more of your second view.Daniel Roseman
And your full MIDDLEWARE_CLASSES setting.Daniel Roseman
@DanielRoseman: I added them.eugene
Is the cookie set properly and stored in the db?maulik13
@maulik13: turned out it's indeed client issue. I changed my code to share one HttpClient object for all requests and it's working correctly now. Thanks for help though!eugene

1 Answers

0
votes

You are right about http being stateless. However using cookie can help you maintain state of the request. When you call login function Django will save the user ID (encrypted value) in the cookie named sessionid. So the next time you get a request from the user, the browser will also send this cookie in the request header.

If you look at the table named *django_session* you should see an entry where session_key has the same value as cookie sessionid.

AuthenticationMiddleware keeps track of a user authentication and assigns user object to request.user

SessionMiddleware tracks session data for a user

That's how Django will track a user and its session.

If you really want to look into details you could have a look at authentication middleware code (django.contrib.auth.middleware), especially process_request to check how a user is added in request object.

Perhaps this is useful in debugging your issue?

EDIT:

Based on what helped Eugene from the comments.

When it's session related issue (login or session data) it's a good idea to check if the cookie is set properly on the client side. If it's a desktop browser, a tool like Firebug can be helpful by reading the http headers in "Net" tab of Firebug.

In Eugene's case it's an Android client, so one option is to debug Django middleware to check the values for request.COOKIE. If you are not receiving right cookies on Django end then the cookie is not set properly on the client side. One of the reasons for this on a browser is cookies could be disabled.

So it's a good idea to check client side settings to make sure cookies are stored and sent correctly.