Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django session on mobile applications

Tags:

django

session

We are currently developing a mobile application(using ionic) for our site that was built using Django. We used django sessions on the site everytime a user logs in. From what I understand, django session sets the session id in the client that is stored in the cookie of the browser. How can we set this session id in the mobile app, if the mobile app is separate from django?

like image 285
Al Ryan Acain Avatar asked May 19 '16 07:05

Al Ryan Acain


People also ask

Can Django be used for mobile apps?

Short answer: Yes, Django would be a perfectly suitable choice for a mobile application backend.

Which session type are supported by Django?

Django provides full support for anonymous sessions. The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis.

How does session authentication work in Django?

With session-based auth, a session is generated and the ID is stored in a cookie. After logging in, the server validates the credentials. If valid, it generates a session, stores it, and then sends the session ID back to the browser.


1 Answers

I see at least three ways you can approach this:

  1. find a way to get your ionic app to work with django's cookies (session and CSRF).
  2. change your django app in three ways: 1) have login/logout views that give an authentication token to the mobile application, 2) extend SessionMiddleware to extract the session id from the authentication token sent via the "Authorization" HTTP header of the mobile app's requests, 3) extend django's CSRF middleware to make requests that do not come from web browsers exempt from CSRF checks.
  3. try to use existing solutions for adding JWT (Json Web Token) authentication to Django.

Getting WebView-based hybrid mobile apps to work properly with cookies on both android and ios seems to be non-trivial (e.g. Handling cookies in PhoneGap/Cordova).

The existing solutions for JWT-auth I found thus far don't seem to use Django's sessions (which I find rather convenient for the sake of having a uniform solution for killing the sessions of users who get their phones/computers stolen or their accounts hacked). If someone knows of a pluggable solution that does token-authentication on top of django's regular sessions, please comment.

To elaborate on method 2:

  • When your mobile app doesn't handle cookies, it can't even log in due to Django's CSRF check. That's why requests coming from your mobile app need to be exempt from CSRF protection.

Note: Do NOT simply disable CSRF protection. While the mobile application isn't vulnerable to CSRF attacks, the browsers of people who are visiting the existing website still are.

  • To extend the CSRF mechanism to exempt non-browser requests, you need an effective way to determine whether a request is coming from a web browser. There's a bunch of HTTP headers (E.g. Referer, Cookie, X-Requested-With, Origin) we can look at to get an idea. Let's assume for now that your legitimate website users don't spoof their headers.

  • Use the same "is-web-browser"-check you used for CSRF-exemption to protect the mobile app's login/logout views.

Example Code (for an Android mobile app, iOS headers coming from the mobile app are likely different):

def is_mobile_app_access(request):
    return request.META.get('HTTP_REFERER', None) is None 
        and request.META.get('HTTP_COOKIE', None) is None 
        and request.META.get('HTTP_X_REQUESTED_WITH', None) == 'your.app.name.here' 
        and request.META.get('HTTP_ORIGIN', None) == 'file://'

class CustomCsrfViewMiddleware(CsrfViewMiddleware):
    def process_view(self, request, callback, callback_args, callback_kwargs):
        if is_mobile_app_access(request):
            return None
        else:
            return super(CustomCsrfViewMiddleware, self).process_view(request, callback, callback_args, callback_kwargs)

    def process_response(self, request, response):
        if is_mobile_app_access(request):
            return response
        else:
            return super(CustomCsrfViewMiddleware, self).process_response(request, response)


class CustomSessionMiddleware(SessionMiddleware):
    def process_request(self, request):
        if is_mobile_app_access(request):
            session_key = request.META.get("HTTP_AUTHORIZATION", None)
        else:
            session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        request.session = self.SessionStore(session_key)

If anyone sees something fundamentally wrong with this approach, please let me know. I suppose the weakest link in this approach is how reliable the is_mobile_app_access check is.

What did you end up doing?

like image 78
sabine Avatar answered Oct 17 '22 12:10

sabine