Django REST framework JWT Authentication Sign up API with email confirmation.
Getting started
This tutorial is an extension of the first part of JWT Authentication in the Django REST framework. In this section, we will focus on implementing user registration over a REST API with email account verification.
- First part of this tutorial: Django REST API with JWT Authentication
- Third part: Social provider authentication (Sign in with Google, etc.)
- Code repository: mich0232/drf-jwt-register-tutorial
Step 1 — Install required packages
If you want to allow users to register via a REST API, dj-rest-auth
provides a registration feature. It uses django-allauth
, so we need to install it first and set it up.
Install requirements & basic setup
- Start by installing
dj-rest-auth[with_social]
, as it ensuresdjango-allauth
is installed.
# requirements.txt
Django==5.0.6
djangorestframework==3.15.2
djangorestframework-simplejwt==5.3.1 # JWT token implementation for DRF
dj-rest-auth[with_social]==6.0.0 # REST API authentication utils
2. Add django.contrib.sites
, allauth
, allauth.account
, and dj_rest_auth.registration
apps to INSTALLED_APPS in your django settings.py:
INSTALLED_APPS = [
...,
'django.contrib.sites',
...
'rest_framework',
'rest_framework.authtoken',
...
'allauth',
'allauth.account',
'allauth.socialaccount',
'dj_rest_auth.registration',
]
# django.contrib.sites
SITE_ID = 1
3. Add allauth.account.middleware.AccountMiddleware
to MIDDLEWARE in settings.py
MIDDLEWARE = [
...
"allauth.account.middleware.AccountMiddleware",
]
4. Add django-allauth
settings to Django’s settings.py. For now, we will disable the email verification feature and address it later.
ACCOUNT_AUTHENTICATION_METHOD = "email" # Use Email / Password authentication
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = "none" # Do not require email confirmation
Full list of available settings: Django Allauth Configuration
5. Run Django migrations: python manage.py migrate
Step 2— Available endpoints
Expose the new registration endpoints in urls.py
urlpatterns = [
path("admin/", admin.site.urls),
path("api/v1/auth/", include("dj_rest_auth.urls")),
path('api/v1/auth/registration/', include('dj_rest_auth.registration.urls'))
...
]
Let’s take a look at the newly available endpoints:
/api/v1/auth/registration/ dj_rest_auth.registration.views.RegisterView rest_register
/api/v1/auth/registration/account-confirm-email/<key>/ django.views.generic.base.TemplateView account_confirm_email
/api/v1/auth/registration/account-email-verification-sent/ django.views.generic.base.TemplateView account_email_verification_sent
/api/v1/auth/registration/resend-email/ dj_rest_auth.registration.views.ResendEmailVerificationView rest_resend_email
/api/v1/auth/registration/verify-email/ dj_rest_auth.registration.views.VerifyEmailView rest_verify_email
What we are looking for is the /api/v1/auth/registration/
ehe rest of the endpoints are used during email verification; however, this feature requires emailing to be enabled, so we’ll skip it for now by setting ACCOUNT_EMAIL_VERIFICATION = "none"
in settings.py.
Step 3— Creating a new user
Registration API uses the RegistrationSerializer defined in dj-rest-auth's
settings. By default, it uses dj_rest_auth.registration.serializers.RegisterSerializer
to perform account creation.
Since we’ve set our authentication method to email
via these three settings:
ACCOUNT_AUTHENTICATION_METHOD = "email" # Use Email / Password authentication
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
Call the API — you might need to logout first, from you current user, it order to create a new one. username
field is now optional, if you won’t provide it, username will be generated based on your email address.
User was created successfully.
Override default behaviour
If you want to modify the accepted parameters or perform any action on user creation, you can use a custom RegisterSerializer by specifying it in the settings.
REST_AUTH = {
...
"REGISTER_SERIALIZER": "myapp.serializers.CustomRegisterSerializer",
}
Full list of dj-rest-auth’s settings
Step 4— Email verification (optional)
If you want to enforce email verification for your users, you need to set up email sending in Django first. This can be achieved by using libraries like django-anymail, which supports multiple email service providers, django-ses, which brings an AWS SES email backend to Django.
Gmail SMTP
Using a reliable third-party ESP is recommended, but for the sake of this tutorial, we can also use Gmail’s SMTP service. If you have a Google account, you can use generated app credentials to authenticate against the Google SMTP server to send out emails.
- Go to your Gmail account settings.
2. Enable 2-Step Verification.
3. Type ‘App passwords’ in the search bar above and select it.
4. Copy the generated App password — you can see it only once.
Django settings
First, we need to add some Django settings to set up email sending. These settings come directly from Django and do not require any additional packages to be installed.
# Django SMTP
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.gmail.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "<your-email-address>" # email sending address
EMAIL_HOST_PASSWORD = "<app-password>"
Now, let’s tell dj-rest-auth
along with django-allauth
that users should confirm their emails before signing in.
ACCOUNT_EMAIL_VERIFICATION = "mandatory" # Require email confirmation
ACCOUNT_CONFIRM_EMAIL_ON_GET = True # No need to sent POST request to confirmation link
LOGIN_URL = "/admin" # Path, users will be redirected to after email verification
You can apply further customization with: ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL
Test the integration
A confirmation email was sent; we need to confirm it before we are allowed to sign in.
Go to your inbox and click the verification link.
If you click this link, you will probably get a TemplateResponseMixin
exception.
TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
That’s because, if you take a look at the endpoints we checked earlier, account-confirm-email
endpoint points to a placeholder TemplateView.
/api/v1/auth/registration/account-confirm-email/<key>/ django.views.generic.base.TemplateView account_confirm_email
Manually add the ConfirmView to your URLs. Make sure you add it before the generic TemplateView definition.
from allauth.account.views import ConfirmEmailView
urlpatterns = [
...
re_path(
"^api/v1/auth/registration/account-confirm-email/(?P<key>[-:\w]+)/$",
ConfirmEmailView.as_view(),
name="account_confirm_email",
),
path('api/v1/auth/registration/', include('dj_rest_auth.registration.urls')),
]
Click the link again and you should be redirected to your admin page. Or any page that you set as: LOGIN_URL
If you need more customisation, you can set additional redirect rules in the settings.
import os
# The URL to redirect to after a successful email confirmation, in case no user is logged in.
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = os.environ.get(
"EMAIL_CONFIRM_REDIRECT_URL", "https://myapp.com/login"
)
# The URL to redirect to after a successful email confirmation, in case of an authenticated user.
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = os.environ.get(
"EMAIL_CONFIRM_REDIRECT_URL", "https://myapp.com/login"
)
How to change the website domain in email messages?
The default example.com is the name of the Django Site created by default. You can edit its name via the Django Admin.
How to change the email verification template to send custom emails?
You can override the template(s) by placing a file with the correct name in your Django project.
Tell Django it should look for templates in one extra directory. We will populate it in a moment.
TEMPLATES = [
{
...
'DIRS': [BASE_DIR / 'templates'],
...
},
]
Start by creating a few nested directories: /templates/account/email
, in the root of your project.
Now you can create three files to override the HTML content, plain text content, and the email subject.
- email_confirmation_signup_message.txt
Hello {{ user.username }},
This is a custom message, please click the link below to confirm you email address:
[Confirm Email: {{ activate_url }}]
Best, Michał
- email_confirmation_signup_message.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DRF JWT Tutorial</title>
</head>
<body>
<center class="wrapper">
<table class="main" width="100%">
<tr>
<td style="padding: 20px">
<div>
<h3>Hello {{ user.username }}</h3>
<p>
This is a custom message, please click the link below to confirm you email address:
</p>
<p>
<a href="{{ activate_url }}">Confirm Email</a>
</p>
<p>
Best, Michał
</p>
</div>
</td>
</tr>
</table>
</center>
</body>
</html>
- email_confirmation_signup_subject.txt
Confirm your drf-jwt-tutorial account!
Test the email again.
Conclusion
In this tutorial, we installed dj-rest-auth[with_social]
, which usesdjango-allauth
underneath to handle user management. We exposed a user registration API and tested it. Lastly, we set up an email sending service and set email verification as mandatory during sign-up.
Code Repository
Example code from this tutorial is available in my GitHub repository:
https://github.com/Mich0232/drf-jwt-register-tutorial
Further reading
Please make sure you check out the other parts of this tutorial:
- First part — the basic setup: Django REST API with JWT Authentication
- Third part — social provider authentication (Google, etc.)
Thank you for reading!