Friday, October 31, 2014

Django Mobile Backend Login

Disclaimer: There are many things in this entry which are incomplete in some cases, for example when I say mobile applications don't have the "session"s, it is a general statement, of course you can use libraries or custom methods to build sessions.


We all know how pain in the ass authentication may become if you are inexperienced in mobile backend development.

It is different from website development, there are no sessions. You can't send a login request once and forget about it for the following requests. You have to keep user logged in, he may leave and come back 1 month later, who would want to be welcomed back by a login screen in a mobile application anyway?

My solution is specific to Django Framework but the main idea is the same.

There are 2 options:
1) At every request include email and password to the request. This way your backend will know no sessions, every request is a new request and at each request you should login your user again. Don't ever worry about few extra bytes this wastes. Nothing would change because of 50 bytes.

2) Make a login request which on successful requests returns a random "token" like 15dsf87yfa8sfas8a7shdas8ah and save it to the database as well under the user, this is basically the same as previous one and you are inventing the "sessions". But don't worry it is a very easy process so don't think it like reinventing the wheel. At every request include this token and login the user with it.

You will need a login request which does nothing! You can ask why would you need a login screen and request when each request already includes login request. Think deeply you open an application and give your credentials. At that exact moment you don't need to change anything at the backend (in Option 1) but you still have to warn user if the credentials are right or wrong. This way user won't be interrupted after his first job-doing request, that's not convenient. This is why you still need a login request which does nothing but just returns {'success':True} or {'success':False}

Here is the Django specific part, I wrote a custom middleware, which is very basic but it does the job:



Here you see at every request I look at GET parameters and login the user as custom Citizen class, because I don't use the regular user class. 

In the view which needs login you can do this:


I am checking isinstance of Citizen because Django adds custom user class and that's not what I care about, the request may have a regular user but that doesn't mean my custom login has ran (in fact it means it was unsuccessful)


You can put your custom middleware class anywhere you want, I put it in Citizen app because logically that's where it belonged:


Then what you need to do is open settings.py and add your middleware path to is like this:




Of course the best way to develop mobile backend with Django is using Django Rest Framework and probably there is a better way to handle this authentication with AuthenticationMiddleware shipped with Django but everyday I am developing with a new framework so this solution works as is, I couldn't find a clear solution to this utilizing them under 30 minutes so I implemented one.

One note: I did use GET for test purposes, at production use POST and don't ever forget using SSL except when it's just a hobby project.

Happy Djangoing