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: 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 ListAPIView.
# users/views.py from rest_framework import generics from . import models from . import serializers class UserListView(generics.ListAPIView): 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.
Want to learn more about Django APIs? I’ve written an entire book on the subject called Django for APIs. The first two chapters are available to read for free.