4

I'm currently trying to implement "Remember Me" feature in Django.

I'm using both SessionAuthentication from Django REST framework and JSONWebTokenAuthentication from djangorestframework-jwt.

However, I don't know how to implement the concept of "Remember Me" for these two authentications. Like how do I extend the session forever and how do I extend the token forever (I'm using JWT auth for mobile & desktop - Session auth for browser).

Also, what is the secure way to implement this feature for both authentications?

Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
Tim
  • 1,029
  • 2
  • 14
  • 23

3 Answers3

8

There are a few things here that I should make clear ahead of time: how authentication works and where expiration comes into play for SessionAuthentication and JSONWebTokenAuthentication.

Session Authentication

The SessionAuthentication class provided by Django REST framework is really just small layer over the session framework provided by Django. So if you can implement a "remember me" function in Django using their sessions, DRF will also inherit it.

Luckily, someone already asked about that on Stack Overflow: Django “Remember Me” with built-in login view and authentication form

Basically it comes down to changing the SESSION_COOKIE_AGE setting (2 weeks by default) to a very high number. Also make sure to keep in mind the implications of having long-lived sessions, and perhaps check out how long the session cookies are by default on websites you visit (typically anywhere from 2 weeks to 6 months).

JSON Web Tokens

The JSONWebToken authentication class provided by django-rest-framework-jwt authenticates requests based on JSON Web Tokens. By default, tokens expire in five minutes but can be refreshed for up to seven days.

The token expiration time is controlled by the JWT_EXPIRATION_DELTA setting. It is not recommended to extend this time too large, but instead use refresh tokens for long-lived tokens. You can enable refresh tokens with the JWT_ALLOW_REFRESH setting and control the expiration time with the JWT_REFRESH_EXPIRATION_DELTA setting.

Community
  • 1
  • 1
Kevin Brown-Silva
  • 40,873
  • 40
  • 203
  • 237
  • So for mobile or desktop app talking to the server using JWT, should I store the username and password in local database and keep requesting token for 'Remember Me' feature? Or should I just save the token, but use expiration time like 1 day and keep refreshing? – Tim May 25 '15 at 05:28
  • @TimNguyen I'd _highly recommend_ storing the refresh token in the local database. Storing their username and password in plain text (or even lightly encrypted) is risky, storing an easily revocable token with an expiration is _not as risky_. – Kevin Brown-Silva May 25 '15 at 14:27
  • django-rest-framework-jwt won't give me a refresh_token and that's driving me crazy! I am setting `JWT_ALLOW_REFRESH` property as True and setting `JWT_REFRESH_EXPIRATION_DELTA` for a long long time. The behaviour I expect is to be given a `refresh_token` but that is not happening. The one token I get does not work for token refreshing after the `JWT_EXPIRATION_DELTA` is reached. Am I missing something? – Alvaro Jun 29 '15 at 14:16
-1

In setting file you have to set:

SESSION_EXPIRE_AT_BROWSER_CLOSE = True

In template :

provide a checkbox with name="remember_me" value="1"

In login function (view.py or ajax.py) write this code when username and password matches,

try:
    remember = request.POST['remember_me']
    if remember:
        settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = False
except MultiValueDictKeyError:
    is_private = False
    settings.SESSION_EXPIRE_AT_BROWSER_CLOSE = True
Nishant Nawarkhede
  • 8,234
  • 12
  • 59
  • 81
Nids Barthwal
  • 2,205
  • 20
  • 12
-1

Dependencies

from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate
from site_user.models import User

This code will revoke username and password from session when we are at login page

def home(request):
    if request.session.has_key('username') and request.session.has_key('password'):
        username = request.session['username']
        password = request.session['password']
        context_dict = {'username': username, 'password': password}
        return render(request, 'sadmin/login.html', context=context_dict)
    else:
        context_dict = {'username': '', 'password': ''}
        return render(request, 'sadmin/login.html', context=context_dict)

The following code is used for user authentication. Here 'is_remember_check' checkbox field from HTML file

@csrf_exempt
def login(request):
    if request.method == "POST":
        if request.POST['is_remember_check'] == 'true':
            request.session['username'] = request.POST['username']
            request.session['password'] = request.POST['password']

        user = authenticate(username=request.POST['username'], password=request.POST['password'])

        if user is not None:
            return JsonResponse({'result': request.POST, 'status': True})
        else:
            return JsonResponse({'result': request.POST, 'status': False})

AJAX call from login page

function login(){
    remember_checkbox_value = document.getElementsByName('remember')[0].checked;
    username = document.getElementsByName('username')[0].value;
    password = document.getElementsByName('password')[0].value;
    var post_data = {username:username, password:password, is_remember_check:remember_checkbox_value};

    $.ajax({
                url: '/sadmin/login/',
                method: 'POST',
                data: post_data,
                dataType: 'json',
                success: function (response) {
                        if (response.status){
                        alert("User login is successful");
                        window.location.reload();
                        }
                        else{
                        alert("User login is not successful");
                        window.location.reload();
                        }
                }
        });
}

HTML Code

<div class="form-actions">
            <label class="checkbox">
            <input type="checkbox" name="remember"/> Remember me </label>
            <button type="button" class="btn green-haze pull-right" onclick="login()">Login <i class="m-icon-swapright m-icon-white"></i>
            </button>
        </div>
Abhisek
  • 444
  • 4
  • 9