Create email login authentication with django-allauth in Django

| Tag python  django  auth 

Django-allauth integrate set of Django applications addressing authentication, registration, account management as well as 3rd party (social) account authentication.

Create custom user model

see [[Create custom user model in Django]].

Install django-allauth

pip install django-allauth

add to INSTALLED_APPS and MIDDLEWARE

Add allauth and allauth.account feature to settings.py, allauth depends on Django site framework, so we need to add it as well:

INSTALLED_APPS = [
	# ...
    'django.contrib.sites',

    # third-party
    'allauth',
    'allauth.account',
]

MIDDLEWARE = [
	# ...
    'allauth.account.middleware.AccountMiddleware',
]

AUTH_USER_MODEL = 'accounts.CustomUser'
# django-allauth config
SITE_ID = 1

authentication backends

Django sets AUTHENTICATION_BACKENDS108 setting to 'django.contrib.auth.backends.ModelBackend' implicitly, which is used when Django attempts to authenticate a user.

Add the django-allauth specific authentication option, which will allow us to switch over to using login via email.

# django-allauth config
SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

Email backend

Django sets EMAIL_BACKEND implicitly, by default Django will look for a configured SMTP server to send emails.

django-allauth will send such an email upon a successful user registration. For test purpose, we can have Django output any emails to the command line console by updating the EMAIL_BACKEND setting:

# django-allauth config
LOGIN_REDIRECT_URL = 'home'
ACCOUNT_LOGOUT_REDIRECT = 'home'
SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # new

Or we can disable email verification by set ACCOUNT_EMAIL_VERIFICATION = "none"

account logout redirect

The default setting for ACCOUNT_LOGOUT_REDIRECT is /.

django-allauth’s ACCOUNT_LOGOUT_REDIRECT actually overrides the built-in LOGOUT_REDIRECT_URL. We can move the two redirect lines under django-allauth config section:

# django-allauth config
LOGIN_REDIRECT_URL = 'home'
ACCOUNT_LOGOUT_REDIRECT = 'home'
SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

run migrate to update DB

python manage.py migrate

URLs

Include allauth.urls in project’s urls.py file, under path accounts/:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('allauth.urls')),
]

We’ll have URLs such as /accounts/login/, /accounts/signup/,.etc.

Templates

Django’s auth app looks for templates within a registration directory, but allauth prefers they be located within a account directory(not accounts). We’ll need to provide template files such as account/login.html, account/signup.html, account/logout.html.

The URL names from allauth are different with the ones from auth, all of the URL name from allauth have a account_ prefix, so Djanog’s logout will now be account_logout, …

<ul class="navbar-nav me-auto mb-2 mb-md-0">
	<li class="nav-item"><a class="nav-link" href="{% url 'about' %}">About</a></li>
	{% if user.is_authenticated %}
		<li class="nav-item"><a class="nav-link" href="{% url 'account_logout' %}">Log Out</a></li>
	{% else %}
		<li class="nav-item"><a class="nav-link" href="{% url 'account_login' %}">Log In</a></li>
		<li class="nav-item"><a class="nav-link" href="{% url 'account_signup' %}">Sign Up</a></li>
	{% endif %}
</ul>

Log in page

The template file is account/login.html.

Now the login page has a Remember Me box option by default, we can remove it by setting ACCOUNT_SESSION_REMEMBER = True:

# django-allauth config
LOGIN_REDIRECT_URL = 'home'
ACCOUNT_LOGOUT_REDIRECT = 'home'
SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
ACCOUNT_SESSION_REMEMBER = True # new

Log out page

Click logout will display a log out confirmation page, the template of which is account/logout.html:

{% extends "_base.html" %}
{% load crispy_forms_tags %}

{% block title %}Log In{% endblock title %}

{% block content %}
    <h2>Log Out</h2>
    <p>Are you sure you want to log out?</p>
    <form method="post" action="{% url 'account_logout' %}">
        {% csrf_token %}
        {{ form|crispy }}
        <button class="btn btn-danger" type="submit">Log Out</button>
    </form>
{% endblock content %}

Sign up page

The template is account/signup.html.

An optional customization we can make via django-allauth is to only ask for a password once:

# django-allauth config
LOGIN_REDIRECT_URL = 'home'
ACCOUNT_LOGOUT_REDIRECT = 'home'
SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False # new

Email only login

This requires a few changes. First we’ll make username not required, but set email instead to be required. Then we’ll require email to be unique and the authentication method of choice:

# django-allauth config
LOGIN_REDIRECT_URL = 'home'
ACCOUNT_LOGOUT_REDIRECT = 'home'
SITE_ID = 1
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
ACCOUNT_USERNAME_REQUIRED = False # new
ACCOUNT_EMAIL_REQUIRED = True # new
ACCOUNT_UNIQUE_EMAIL = True # new
ACCOUNT_AUTHENTICATION_METHOD = 'email' # new

Prev     Next