No Brainer Authentication in Django & React with Redux — Part 1

https://i.morioh.com/39b881aa45.png

I’ve been a Django user for as long as I can remember and I used to despise frontend Javascript frameworks since forever. I believe the reason for that might’ve been me picking Angular as my first framework and just giving up on seeing how hard it was. I wasn’t at all familiar with Typescript and I absolutely hated how everything was set up.

Fearing the same, I tried to shy away from React for a long time as well before giving into the pressure online and finished the TicTacToe guide from the official documentation — what a breath of fresh air. I was immediately hooked.

Since then, I’ve also learned Vue which is, by far, the best Javascript framework I’ve had the pleasure of using. But Vue lacks strong support for Typescript which is something I’ve recently come to love. Vue 3 is supposed to have better integration with Typescript but things like Vuex and Vue Router are still not ready for the next version so I’ll be holding my judgements until they have a final release.

React, on the other hand, has superb integration for Typescript. I’ve come to appreciate the default create-react-app template with Typescript. It comes with Typescript support out of the box and it’s all a React developer should ever need.

Now something that has always bothered me is the quality of tutorials out in the world for a specific problem that people face when working with a JS framework — authentication. There’s a ton of ways to solve this particular problem — sessions, database tokens, JWTs, and I’m sure there’s a new one by the time I’ve written this.

Django has support for all of them. In fact, if you don’t use a frontend framework and rely on the contrib.auth package for your authentication, you’re using session authentication. If you use Django Rest Framework, you have access to database token authentication. If you’re using any package with the term “JWT” in it… well, you’re using JWT authentication.

Which one is the best? I’m not going to answer that because I know people prefer different ones but I’m not completely sold on session authentication for JS frontend frameworks. While you can use it, I don’t recommend it simply because it’s much more complicated than token based authentication, JWT or otherwise. So I’m going to write about token authentication in this tutorial. Specifically, rest_framework’s token authentication. Why? Because it’s the simplest. And this is supposed to be a final, one stop shop for all React and Django based token authentication. You can use it as a template for all your future projects involving this particular tech stack.

Per usual, start your django project. I’m going to name it djreact —

$ django-admin startproject djreact && cd djreact
$ ./manage.py startapp user

Start a new app called user or whatever you wish to name your model. Why? If we already have django.contrib.auth.models.User, why create a separate User model? Because it’s best practice. Here’s an excerpt from the documentation itself —

If you’re starting a new project, it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you. This model behaves identically to the default user model, but you’ll be able to customize it in the future if the need arises.

In the user/models.py file, define your User model —

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
pass

And that’s it for our model! You can add extra fields like a bio as a CharField or change existing fields, for instance, set unique=True for the email field, but we won’t go too deep into that.

We now need to install djangorestframework and configure it. Install it using pip and add it to INSTALLED_APPS in settings.py along with the authtoken app.

INSTALLED_APPS = [
# ...
# third party apps
'rest_framework',
'rest_framework.authtoken',
# local apps
'user.apps.UserConfig',
]
AUTH_USER_MODEL = 'user.User'
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}

And that’s all for our configuration. The last painful thing left to do is setup a User signal so that a Token is generated every time a User is created.

Create a file signals.py in your user app and enter the following —

If you’re not familiar with signals, think of them as functions that are called based on an action. In this case, the “action” is the post_save signal that is connected to the User model so that every time a User is inserted in the database, our create_auth_token function will be called. And as you see in the code, it simply creates a new Token for the recently added User instance. There are a lot of signals you can use like post_delete, pre_save, etc but this isn’t a tutorial on Django signals. This is all you need to know. The only thing that’s left is to let our app know about this signals.py file. Do so in the user/apps.py.

from django.apps import AppConfig
class UserConfig(AppConfig):
name = 'user'
    def ready(self):
import user.signals

We’re now completely done with our model layer and can now move on to creating our views. But we don’t even have to! rest_framework already provides some helper views and we can use them for obtaining our auth token.

In your urls.py file, clear the contents, and write the following —

from dango.urls import path
from django.contrib import admin

from rest_framework.authtoken.views import obtain_auth_token

urlpatterns = [
path('admin/', admin.site.urls),
path('token/', obtain_auth_token),
]

I usually place this inside an embedded include path to my user app’s urls.py but for our tutorial purposes, this is just fine.

Now make your migrations and migrate them to your database. Create a superuser (or a normal user from the shell but to view the admin page, you need to have a superuser).

$ ./manage.py createsuperuser --username "mentix02" --email admin@admin.com
Password: ****
Password (again): ****

To test whether the auth token was created, send a POST request to the token/ endpoint with the credentials you entered and check if it returns a token.

$ curl -s -d "username=mentix02&password=abcd" -X POST http://localhost:8000/token/ | json_pp
{
"token" : "8e3ae0177bc82a717865bb893caf9821ac094bec"
}

And we’re done with our backend! In the next part, we cover the frontend with React and Typescript.


No Brainer Authentication in Django & React with Redux — Part 1 was originally published in The Startup on Medium, where people are continuing the conversation by highlighting and responding to this story.