Django Authentication and Social Authentication with django-allauth

One of the most popular and powerful libraries that solve the problems of authentication in Django is 'django-allauth'. This library will let you easily create authentication systems with a lot more options and control. You can have things like: an email verification step after a user signs up, letting users login with either username or email, "Remember me" checkbox upon signing in, and more. Along with that, with this library you can let users login to your website using their social accounts like Google or Facebook, among many others. This library integrates both the systems seamlessly, and hence the name.

Outline

In this tutorial I'll create an authentication system that will have the following features:

  • A Sign Up page, with fields for username, email, password, password confirmation and a checkbox to agree to Terms of Service.
  • A Sign In page, with a field to enter either username or email, a password field and a "Remember me" checkbox to remember the user's session.
  • Password change, set and reset pages.
  • Google and Twitter oAuth setup with their buttons on the sign-in page.

Installation

This involves: (i) installing the allauth library using pip, (ii) adding settings in your settings.py file, (iii) pointing urls to allauth urls and then finally (iv) doing a migrate.

(i) Install the library with this command:

pip install django-allauth

(ii) In your settings.py, edit with the following:

# Specify the context processors as follows:
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                # Already defined Django-related contexts here

                # `allauth` needs this from django
                'django.template.context_processors.request',
            ],
        },
    },
]

AUTHENTICATION_BACKENDS = (

    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',

    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend',

)

INSTALLED_APPS = (
    # The following apps are required:
    'django.contrib.auth',
    'django.contrib.sites',

    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    # The providers that we want:
    'allauth.socialaccount.providers.google',
    'allauth.socialaccount.providers.twitter',
)

SITE_ID = 1

(iii) In your project's urls.py, add the following pattern:

urlpatterns = [
    # Add this line, among other patterns:
    url(r'^accounts/', include('allauth.urls')),
]

(iv) Run a migrate to create the tables in the database:

python manage.py migrate

Basic Authentication

Since we set that pattern in the 'urls.py' file of our project. All the views related to the authentication system will be available at 'accounts/' in your browser.

Following are all the url patters that you can try and get a view for in the browser.

^admin/
^accounts/ ^ ^signup/$ [name='account_signup']
^accounts/ ^ ^login/$ [name='account_login']
^accounts/ ^ ^logout/$ [name='account_logout']
^accounts/ ^ ^password/change/$ [name='account_change_password']
^accounts/ ^ ^password/set/$ [name='account_set_password']
^accounts/ ^ ^inactive/$ [name='account_inactive']
^accounts/ ^ ^email/$ [name='account_email']
^accounts/ ^ ^confirm-email/$ [name='account_email_verification_sent']
^accounts/ ^ ^confirm-email/(?P<key>[-:\w]+)/$ [name='account_confirm_email']
^accounts/ ^ ^password/reset/$ [name='account_reset_password']
^accounts/ ^ ^password/reset/done/$ [name='account_reset_password_done']
^accounts/ ^ ^password/reset/key/(?P<uidb36>[0-9A-Za-z]+)-(?P<key>.+)/$ [name='account_reset_password_from_key']
^accounts/ ^ ^password/reset/key/done/$ [name='account_reset_password_from_key_done']
^accounts/ ^social/
^accounts/ ^google/
^accounts/ ^twitter/

So if you go to 'accounts/login/' you will see a page like this:

Login Page

Everything related to the basic authentication including this login form will work. In order to make it look the way you want, you'll now have to create templates for each of these views that will override the default templates.

The default templates that allauth uses can be found in their Github repo templates directory.

In your project's root, create a folder named 'templates' (if not already created). In this folder create files for whichever default template you want to override.

As an example, located in 'accounts' folder is a template named signup.html that shows the Signup page and it looks like this:

{% extends "account/base.html" %}

{% load i18n %}

{% block head_title %}{% trans "Signup" %}{% endblock %}

{% block content %}
<h1>{% trans "Sign Up" %}</h1>

<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p>

<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}
  {{ form.as_p }}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <button type="submit">{% trans "Sign Up" %} &raquo;</button>
</form>

{% endblock %}

If I wanted to override this, I will create an 'accounts' folder in the 'templates' directory and create a signup.html file in it, to mirror that. An example of what it might look like:

{% extends "base.html" %}

{% block title %}Signup{% endblock %}

{% block content %}

<p>Already have an account? Then please <a href="{{ login_url }}">sign in</a>.</p>

<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
  {% csrf_token %}
  {{ form.as_p }}
  {% if redirect_field_value %}
  <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
  {% endif %}
  <button type="submit" class="btn btn-blue">Sign Up</button>
</form>

{% endblock %}

I made it use my own base.html file that I use for all my templates. I also decided to remove all the code for translation as I didn't need that. And I added some css classes to help with my custom styling.

You should now create custom templates for all the default ones that you need to override, which should be most of them.

Defining the Site

There is just one bit that you need to do now. Go to your admin, find "Sites" and click on it. In that you will fine 'example.com', click on that and then enter in the domain and display name of your site. The domain and Display name will be used by allauth in the emails sent to the users.

Accepting Terms of Service

The django-allauth library provides many configuration options. One of which is to define a custom form class for the signup view. I'm going to show you how to create a custom form so to also have an "Accept terms of service" checkbox that users will have to check before they can signup to your site.

For this part you will have to create a form class in one of your apps. I'll refer to mine as 'accounts'.

In account's forms.py:

from django import forms

class SignupForm(forms.Form):
    accept_tos = forms.BooleanField(required=True, label='Accept terms of service')

    def signup(self, request, user):
        user.accept_tos = self.cleaned_data['accept_tos']
        user.save()

We created a BooleanField that uses a Checkbox widget by default and set it as required.

In your settings.py

ACCOUNT_SIGNUP_FORM_CLASS = 'accounts.forms.SignupForm'

This is a setting provided by allauth, and we use it to point to our custom form.

Now if you go to 'accounts/signup/ you will find the checkbox that users will have to fill. You'd probably want to change signup.html and handle the form fields manually to display the checkbox properly. See Rendering fields manually.

Following are some additional settings from allauth's configuration page that you might want to implement.

ACCOUNT_EMAIL_REQUIRED = True # Require e-mail address when signing up
ACCOUNT_AUTHENTICATION_METHOD = "username_email" # Allowing login with either username or email
ACCOUNT_EMAIL_VERIFICATION = "mandatory" # Verifying the email address will be compulsory
ACCOUNT_USERNAME_BLACKLIST = ['administrator', 'help', 'helpdesk', 'operator', 'root', 'superadmin', 'superuser'] # Ban a list of names as a choice for a username

Please read the linked configuration page for all the options and their complete explanation.

With this, you should now have a complete basic authentication system. Next we will look at the social authentication option that allauth provides.

Social Authentication

Setting up social authentication is quite simple for most of the providers. In this tutorial I'll show how to do it for Google and Twitter.

Google

Generating Client ID and Secret Key

  • Go to Google's Developer console
  • Click on Credential, then on "OAuth content screen" and enter in the required details.
  • Under "Credentials" tab, click "create Credentials" then "OAuth Client ID"
  • Choose Web Application
  • For "Authorized JavaScript origins", enter http://127.0.0.1:8000 for localhost or your own domain for a live site.
  • For "Authorized redirect URIs", enter http://127.0.0.1:8000/accounts/google/login/callback, or with your own domain, as appropriate.
  • After clicking Save, you will be shown a client ID and client secret.

The client ID and client Secret is what we need to enter in our Django application.

Creating a Social Application for Google

  • Go to the admin of your site and click "Add" next to "Social Applications".
  • Choose Google from the Provider list.
  • Enter "Google" for the Name field, or something similar.
  • For Client ID, enter the obtained client ID.
  • For Secret Key, enter the obtained client secret.
  • Leave the Key field empty.
  • Choose your site from Available Sites and push it to Chosen sites.
  • Hit Save.

Twitter

Generating Client ID and Secret Key

  • Create a verified Twitter account.
  • Go to Creating an app with Twitter page.
  • Give your app a name and a description.
  • For website, enter http://127.0.0.1:8000 for localhost, or your own domain.
  • For Callback URL, enter http://127.0.0.1:8000/accounts/twitter/login/callback, or your own domain.
  • After the app is created you will need to select “Allow this application to be used to Sign in with Twitter” in the settings.

Note down the Consumer Key (API Key) and Consumer Secret (API Secret)

Creating a Social Application for Twiiter

  • Go to you Admin and click "Add" next to "Social Applications".
  • Choose Twitter from the Provider list.
  • Enter "Twitter" for the Name field, or something similar.
  • For Client ID, enter the obtained Consumer Key.
  • For Secret Key, enter the obtained Consumer Secret.
  • Leave the Key field empty.
  • Choose your site from Available Sites and push it to Chosen sites.
  • Hit Save.

Note: Just to be clear, for all of the urls in the above, you will have to replace http://127.0.0.1:8000 with your own domain, like http://www.example.com/accounts/twitter/login/callback/, for example.

You should now be able to click on the Google and Twitter links in the 'accounts/login' page and sign in with those.

Just like the basic authentication, there are few setting options that allauth provides, so do check out all the configuration options available.

Closing

As you saw django-allauth makes it really simple to create pretty much any kind of authentication system that most websites might need. Make sure you read their documentation.

Share your thoughts below and thank you for reading.

blog comments powered by Disqus