Django + React Authentication : Part 1
By: Tarric Sookdeo
Tags: Programming, Authentication, Rest Api, Web Development, Python

Django Backend API

Setting up the virtual environment and installing dependencies:

The project will be setup using pipenv. For more information on pipenv you can check out my in depth article here.

Go to your desired project location in terminal and create the project folder, then cd into it. I will be calling it django-react-auth :

mkdir django-react-auth

cd django-react-auth

Once inside the project directory setup the virtual environment using pipenv and activate it:

pipenv install --python 3.9

pipenv shell

Note: at the time of writing Python 3.9 is the latest stable version of Python. Django 3.1 will be used for this project. Django 3.1 requires Python 3.6+ due to the async/await syntax. You can use whichever version of Python you’d like so long as it’s Python 3.6 or greater.

Once the virtual environment is setup, you should see a Pipfile and Pipfile.lock in the django-react-auth directory. We will now install the needed pip packages. Make sure your virtual environment is activated and run the following in terminal:

pipenv install django djangorestframework django-rest-auth django-allauth django-cors-headers

What are these pip packages?

django: The Django framework is the backbone of the whole project.

django-rest-framework: DRF will give us the tools needed to serialize data and turn our Django application into a RESTful API.

django-rest-auth: Gives us the logic, and endpoints needed for user authentication. Saves a lot of time vs writing everything from scratch.

django-allauth: Allows us to further customize the authentication system. Also provides the endpoints needed for user registration.

django-cors-headers: Django is shipped with a lot of security features. This package will allow us to specify domains where requests can be made from. Without this, all requests from the React frontend will be denied.

The Django Project and Apps:

Now that we have things setup, it’s time to create the Django project in the django-react-auth directory:

django-admin startproject mysite .

I am naming the project mysite . Note the period at the end of the command. This will create the project in the current directory instead of making a whole new one. The projects file structure should look like this now.

- django-react-auth

-- mysite

--- __init__.py

--- asgi.py

--- settings.py

--- urls.py

--- wsgi.py

-- manage.py

-- Pipfile

-- Pipfile.lock

Note: In a real world project you would hide sensitive information in the settings.py file such as the secret key and database credentials. For simplicity sake we will leave those alone here. However, in a real project please do your due diligence to prevent a security nightmare.

If you run the Django development server using the following command in the terminal:

python manage.py runserver

You should see something like this in the terminal:

And if you head to http://127.0.0.1:8000/ you should see the development server is running:

Notice the unapplied migrations warning in the terminal. It is important to NOT migrate before creating our custom user model which we will do now.

Creating a Custom User Model:

A custom user model will allow you to expand it later on if you need to. It is best to do this as soon as you start your project to get it out of the way. The official Django documentation even recommends creating a custom user model. We will do this the simple way, by extending the already built in user model.

First create the users app where the custom user model will live, and add it to the installed app list in settings.py .

Terminate the development server in terminal and run the following command to create the app:

python manage.py startapp users

You should see a new users folder in your project with a few files. Add the users app to the INSTALLED_APPS list in settings.py . While we are at it, let’s also add the 3rd party apps we installed via pip to the list:

# mysite/settings.py

...

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

# 3rd Party Apps

'rest_framework', # new

'rest_framework.authtoken', # new

'rest_auth', # new

'django.contrib.sites', # new

'allauth', # new

'allauth.account', # new

'allauth.socialaccount', # new

'rest_auth.registration', # new

'corsheaders', # new # Local Apps

'users', # new

]

...

To create the custom user model, go into the models.py :

# users/models.py from django.contrib.auth.models import AbstractUser

from django.db import models class CustomUser(AbstractUser):

# Any extra fields would go here

def __str__(self):

return self.email

We don’t have any extra user fields here. However, if we did want to add fields such as birthday, and address you can easily do it here.

Whenever you create a custom user model you need to point Django to it. Head back to settings.py and add this to the bottom of the file to do so:

# mysite/settings.py ... AUTH_USER_MODEL = 'users.CustomUser'

If we were to add any extra fields to our custom user model we would need to modify the built in forms to handle them. To do this we need to create a forms.py file and extend Django’s built in form classes for the user model.

touch users/forms.py

Add the following code:

# users/forms.py from django import forms

from django.contrib.auth.forms import UserChangeForm, UserCreationForm from .models import CustomUser



class CustomUserCreationForm(UserCreationForm):

class Meta:

model = CustomUser

fields = ('email', ) class CustomUserChangeForm(UserChangeForm):

class Meta:

model = CustomUser

fields = UserChangeForm.Meta.fields

One of Django’s best built in features is the admin interface. Whenever you create a new app, you can register it so you can interact with it via the admin interface. Head over to admin.py and place the following code:

# users/admin.py from django.contrib import admin

from django.contrib.auth import get_user_model

from django.contrib.auth.admin import UserAdmin from .forms import CustomUserChangeForm, CustomUserCreationForm

from .models import CustomUser class CustomUserAdmin(UserAdmin):

add_form = CustomUserCreationForm

form = CustomUserChangeForm

model = CustomUser

list_display = ['email'] admin.site.register(CustomUser, CustomUserAdmin)

Let’s now take care of our serializers. Using DRF we will be able to easily use a class serializer that will automatically serialize fields into JSON, and back to Python objects when needed. Create a serializers.py file inside of users:

touch users/serializers.py

Inside of serializers.py :

# users/serializers.py from rest_framework.serializers import ModelSerializer from .models import CustomUser class UserSerializer(ModelSerializer):

class Meta:

model = CustomUser

fields = ('email', 'last_login', 'date_joined', 'is_staff')

That is how easy DRF makes it to turn a Python object that is based on a Django model into JSON, and vice versa. Notice the fields variable. This is a tuple of the different model attributes you want to serialize.

Now let’s take care of the URL’s which will be the API’s endpoints. The good news is django-rest-auth and django-allauth provides us with the needed endpoints and logic already. So all we need to do is specify them in a urls.py file in users.

touch users/urls.py

Inside of that:

# users/urls.py from django.urls import include, path urlpatterns = [

path('auth/', include('rest_auth.urls')),

path('auth/register/', include('rest_auth.registration.urls'))

]

We need to add the users/urls.py to the urls.py inside of mysite :

# mysite/urls.py from django.contrib import admin

from django.urls import include, path urlpatterns = [

path('admin/', admin.site.urls),

path('api/v1/users/', include('users.urls')),

]

The last thing to do here is add some configurations to settings.py :

# mysite/settings.py # Specifies localhost port 3000 where the React

# server will be running is safe to receive requests

# from. All all of this.

CORS_ALLOWED_ORIGINS = [

'http://localhost:3000'

] # Add the corsheaders middleware to the top of the

# middleware list. The middleware list will already

# exists and have other items in it.

MIDDLEWARE = [

'corsheaders.middleware.CorsMiddleware',

...

] # Django All Auth config. Add all of this.

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' AUTHENTICATION_BACKENDS = ( "django.contrib.auth.backends.ModelBackend", "allauth.account.auth_backends.AuthenticationBackend",

) SITE_ID = 1

ACCOUNT_EMAIL_REQUIRED = True

ACCOUNT_USERNAME_REQUIRED = False

ACCOUNT_SESSION_REMEMBER = True

ACCOUNT_AUTHENTICATION_METHOD = 'email'

ACCOUNT_UNIQUE_EMAIL = True # Rest Framework config. Add all of this.

REST_FRAMEWORK = {

'DATETIME_FORMAT': "%m/%d/%Y %I:%M%P", 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication',

],

}

That is it! You’ve created a backend API in Django that will allow users to register, login, reset their password, and more using a token based authentication system. You can now migrate the changes.

python manage.py makemigrations

python manage.py migrate

Create a super user (an admin user):

python manage.py createsuperuser

Follow the prompts and fill out the information till you created a superuser.

Testing With Postman

Postman is a tool used to test API’s. It is simple to use and is free. We will make some requests to our API to see if it is working as expected.

Register New User

Keep in mind that to register a user, we need a unique email, a password, and a confirm password field. The request will look like this:

If this works, it will return an authentication token that we can use. If not, we will get an error. Let’s click send:

You’ll see that we got back a key . This is the authentication token and we can send this with subsequent requests.

Logout User

Now that we have a token, we can send it with a post request to the logout endpoint as an Authorization header like so:

Send the request and it will delete the token from the server side, and log the user out.

Conclusion:

We have now created an authentication system API using Django! In the next part we will use React to interact with this authentication system. Stay Tuned!