Django Rest Framework User Authentication Tutorial - Custom User Model + Social Auth
Django Rest Framework is the most popular way to turn a Django website into a modern, robust API. However when it comes time to add user authentication, the official documentation offer a dizzying array of choices.
In this tutorial we will build from scratch a Django API with token-based user authentication. It has a custom user model and uses django-allauth so that we can easily add social authentication via Gmail, Facebook, etc at a later date.
I’ve open-sourced this code as DRFx on Github.
This tutorial assumes you already have Python 3.6x and Pipenv installed. If not, complete instructions can be found here.
First make a new directory for our code, install django, and start a new pipenv shell. Then create a new project called
drfx and a new app
$ cd Destkop $ mkdir drfx && cd drfx $ pipenv install django $ pipenv shell (drfx) $ django-admin startproject drfx . (drfx) $ python manage.py startapp users
users app will have the code for our custom user model. You should start every new Django project with a custom user model since it gives you the opportunity to make changes in the future. The official documentation even says so.
Since we created a new app let’s add it to our
INSTALLED_APPS setting and also signify we’ll be using a custom user model called
CustomUser rather than the default
# drfx/settings.py INSTALLED_APPS = [ ... 'users', ] AUTH_USER_MODEL = 'users.CustomUser'
Next create our model which will have an additional
name field since this is more global-friendly than the last name/first name on the default
# users/models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): name = models.CharField(blank=True, max_length=255) def __str__(self): return self.email
Create a new
users/forms.py file and add the following code. This allows us to make/modify users from the admin app and also within our project itself.
# users/forms.py from django import forms from django.contrib.auth.forms import UserCreationForm, UserChangeForm from .models import CustomUser class CustomUserCreationForm(UserCreationForm): class Meta(UserCreationForm): model = CustomUser fields = ('username', 'email') class CustomUserChangeForm(UserChangeForm): class Meta: model = CustomUser fields = UserChangeForm.Meta.fields
Finally update the
admin.py file so we can see/use our new
CustomUser model and related forms rather than Django’s defaults.
# 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 CustomUserCreationForm, CustomUserChangeForm from .models import CustomUser class CustomUserAdmin(UserAdmin): add_form = CustomUserCreationForm form = CustomUserChangeForm model = CustomUser list_display = ['email', 'username', 'name'] admin.site.register(CustomUser, CustomUserAdmin)
Ok, our custom user model is done! Now for the first time run our migrations and create the initial database. Then create a new superuser account and start the local server with
runserver so we can login to the admin.
(drf-rest-auth) $ python manage.py makemigrations (drf-rest-auth) $ python manage.py migrate (drf-rest-auth) $ python manage.py createsuperuser (drf-rest-auth) $ python manage.py runserver
Login to the admin panel at http://127.0.0.1:8000/admin with the new superuser account. Click on
users and add a new one that we’ll use for testing shortly. I’ve named mine
Now we can add Django Rest Framework as well as django-rest-auth which is a very convenient third-party package providing API endpoints for user registration, login/logout, password change/reset, social auth, and more. We’ll also create an
api app to expose our project’s endpoints.
(drfx) $ pipenv install djangorestframework (drfx) $ pipenv install django-rest-auth (drfx) $ python manage.py startapp api
Add the following settings to
# drfx/settings.py INSTALLED_APPS = [ ... 'rest_framework', 'rest_framework.authtoken', 'rest_auth', 'api', 'users', ]
It’s always a good idea to version your APIs so we’ll set the route as
api/v1/ for our
# drfx/urls.py from django.contrib import admin from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/', include('api.urls')), ]
api app we’ll create a single endpoint that lists all users at
users/ and also include
rest-auth’s routes. Create a new file called
# api/urls.py from django.urls import include, path urlpatterns = [ path('users/', include('users.urls')), path('rest-auth/', include('rest_auth.urls')), ]
We need our own serializer and view to display all existing users. Create a new file called
users/serializers.py and update it as follows.
# users/serializers.py from rest_framework import serializers from . import models class UserSerializer(serializers.ModelSerializer): class Meta: model = models.CustomUser fields = ('email', 'username', )
views.py file uses DRF’s generic ListCreateAPIView.
# users/views.py from rest_framework import generics from . import models from . import serializers class UserListView(generics.ListCreateAPIView): queryset = models.CustomUser.objects.all() serializer_class = serializers.UserSerializer
And we need a
urls.py file too.
(drf-rest-auth) $ touch users/urls.py
Then update it to display
# users/urls.py from django.urls import include, path from . import views urlpatterns = [ path('', views.UserListView.as_view()), ]
Finally we can
migrate our new changes and then try them out.
(drfx) $ python manage.py migrate
If you go to the
users endpoint at http://127.0.0.1:8000/api/v1/users/ you should see the following for your superuser and test user accounts.
Try out login to with an existing account at http://127.0.0.1:8000/api/v1/rest-auth/login/.
And to log out go to http://127.0.0.1:8000/api/v1/rest-auth/logout/.
By adding the
django-allauth package we can also enable user registration as well as social authentication. The first step is to install the package.
(drfx) $ pipenv install django-allauth
The update our
INSTALLED_APPS setting. Make sure to also include an
EMAIL_BACKEND and a
SITE_ID at the bottom of the
# drfx/settings.py INSTALLED_APPS = [ ... 'rest_framework', 'rest_framework.authtoken', 'rest_auth', 'django.contrib.sites', 'allauth', 'allauth.account', 'rest_auth.registration', 'api', 'users', ] EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' SITE_ID = 1
We’ve added new apps so it’s time to update the database.
(drfx) $ python manage.py migrate
The final step is to add a URL for registration to the
# api/urls.py from django.urls import include, path urlpatterns = [ path('rest-auth/', include('rest_auth.urls')), path('rest-auth/registration/', include('rest_auth.registration.urls')), ]
Ok, we’re done! Make sure the local server is running.
(drf) $ python manage.py runserver
Then navigate to our new user registration page at http://127.0.0.1:8000/api/v1/rest-auth/registration/.
You can now create a new user account, login, logout, and view all users via endpoints.