Adding Social Authentication to Django


This tutorial looks at how to add social auth (also known as social login or social signon) to a Django application with Django Allauth. You'll also configure GitHub and Twitter auth as well as regular auth with username and password.

Social login is a form of single sign-on using existing information from a social networking service such as Facebook, Twitter or Google, to sign in to a third-party website instead of creating a new login account specifically for that website. It is designed to simplify logins for end-users and provide more reliable demographic information to web developers. - Wikipedia

Using a social auth has its advantages. You won't need to set up auth for the web application, since it's handled by the third-party, OAuth provider. Also, since providers like Google, Facebook, and GitHub perform extensive checks to prevent unauthorized access to their services, leveraging social auth instead of rolling your own auth mechanism can boost your application's security.

django social auth demo

Social auth is most often implemented with OAuth -- an open standard protocol for authorization -- where a third-party auth provider verifies a user's identity.

Typical flow:

  1. A user attempts to log in to your app using their account from a third-party auth provider
  2. They are redirected to the auth provider for verification
  3. After verification, they are then redirected back to your app
  4. They are then logged in so they can access the protected resources

For more on OAuth, review An Introduction to OAuth 2.

Why would you want to leverage OAuth over rolling your own auth?

Pros:

  1. Improved security.
  2. Easier and faster log-in flows since there's no need to create and remember a username or password.
  3. In case of a security breach, no third-party damage will occur, as the authentication is passwordless.

Cons:

  1. Your application now depends on another app outside of your control. If the provider is down, users won't be able to log in.
  2. People often tend to ignore the permissions requested by OAuth providers.
  3. Users that don't have accounts on one of the providers that you have configured won't be able to access your application. The best approach is to implement both -- e.g., username and password and social auth -- and let the user choose.

Django Allauth vs. Python Social Auth

Django Allauth and Python Social Auth are the two most popular packages for implementing social authentication in Django. Which one should you use?

Django Allauth

Pros:

  1. Django Allauth is one of the most popular Django packages.
  2. It supports over 50 authentication providers (i.e., GitHub, Twitter, Google).
  3. Along with social auth, it also provides regular auth with username and password.
  4. Django Allauth makes it easy to customize the forms used during the auth flow.

Cons:

  1. Despite the package's popularity, the documentation is poorly structured and not meant for beginners.
  2. There's quite a bit of initial setup required to register an OAuth provider, which can be difficult for beginners.
  3. There's 250+ issues on GitHub (as of writing).

Python Social Auth

Pros:

  1. Python Social Auth provides support for several Python web frameworks like Django, Flask, Webpy, Pyramid, and Tornado.
  2. It supports almost 50 OAuth providers.
  3. It supports the Django ORM and MongoEngine ODM
  4. It provides a storage interface to allow users to add more ORMs.

    For example, to see how the storage interface is used to work with the SQLAlchemy ORM, review the code here. Check out the official documentation for more on how to use the storage interface.

Cons:

  1. The documentation is a bit simpler, but it could still use some work with regard to the organization.
  2. Again, there's quite a bit of initial setup required to register an OAuth provider, which can be difficult for beginners.
  3. There's close to 100 open issues on GitHub (as of writing).

Both packages have their ups and downs. However, this tutorial focuses on Django Allauth as it's much more popular and supports social auth and regular auth via username and password.

Django Setup

Let's create a new Django project and configure Django Allauth.

Create a new Django project

Start by creating a virtual environment and installing Django:

$ mkdir django-social-auth && cd django-social-auth
$ python3.9 -m venv .venv
$ source .venv/bin/activate
(.venv)$ pip install Django==3.1.5

Feel free to swap out venv and Pip for Poetry or Pipenv. For more, review Modern Python Environments.

Now create a new project, apply the migrations, and run the server:

(.venv)$ django-admin startproject social_app .
(.venv)$ python manage.py migrate
(.venv)$ python manage.py runserver

Navigate to http://127.0.0.1:8000. You should see the following screen:

django landing page

Configure Django Allauth

Next, let's set up Django Allauth for our Django app.

(.venv)$ pip install django-allauth==0.44.0

For Django Allauth to work with our Django app, update INSTALLED_APPS inside the settings.py file like so:

# social_app/settings.py INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "django.contrib.sites", # new # 3rd party "allauth", # new "allauth.account", # new "allauth.socialaccount", # new # social providers "allauth.socialaccount.providers.github", # new "allauth.socialaccount.providers.twitter", # new
]

First, we added the Django "sites" framework, which is required for Allauth to work properly. We then added the core Allauth apps: allauth, allauth.account, and allauth.socialaccount.

Now add the following to the bottom of settings.py:

# social_app/settings.py AUTHENTICATION_BACKENDS = ( "allauth.account.auth_backends.AuthenticationBackend",
) SITE_ID = 1
ACCOUNT_EMAIL_VERIFICATION = "none"
LOGIN_REDIRECT_URL = "home"
ACCOUNT_LOGOUT_ON_GET = True

Here, we defined the following:

  • We added allauth as the authentication backend. All logging in and out (via OAuth or regular username and password) will now be handled by Allauth.
  • SITE_ID, which is required for Django Allauth to function.
  • ACCOUNT_EMAIL_VERIFICATION = "none" turns off verification emails. Django automatically sets up an email verification workflow. We do not need this functionality right now.
  • LOGIN_REDIRECT_URL = "home" redirects the user to the homepage after a successful login.
  • ACCOUNT_LOGOUT_ON_GET = True directly logs the user out when the logout button is clicked via a GET request. This skips the confirm logout page.

Update the urls.py to include Django Allauth:

from django.contrib import admin
from django.urls import path, include # new urlpatterns = [ path("admin/", admin.site.urls), path("accounts/", include("allauth.urls")), # new
]

Apply the migration files associated with Django Allauth:

(.venv)$ python manage.py migrate

Migrations are important here since a number of new tables are required by Allauth. Don't forget this step!

Create a superuser:

(.venv)$ python manage.py createsuperuser

Templates

Create a new folder called "templates", and add two files to it called _base.html and home.html:

(.venv)$ mkdir templates && cd templates
(.venv)$ touch _base.html home.html

Update TEMPLATES in settings.py so that Django knows where to find the templates:

# social_app/settings.py TEMPLATES = [ { ... "DIRS": [str(BASE_DIR.joinpath("templates"))], ... },
]

templates/_base.html:

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="UTF-8" /> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Django Social Login</title> </head> <body> {% block content %} {% endblock content %} </body>
</html>

templates/home.html

{% extends '_base.html' %} {% load socialaccount %} {% block content %} <div class="container" style="text-align: center; padding-top: 10%;"> <h1>Django Social Login</h1> <br /><br /> {% if user.is_authenticated %} <h3>Welcome {{ user.username }} !!!</h3> <br /><br /> <a href="{% url 'account_logout' %}" class="btn btn-danger">Logout</a> {% endif %}
</div> {% endblock content %}

Create a view to serve up the home.html template:

# social_app/views.py from django.views.generic import TemplateView class Home(TemplateView): template_name = "home.html"

Add the new URL:

# social_app/urls.py from django.contrib import admin
from django.urls import path, include from .views import Home # new urlpatterns = [ path("admin/", admin.site.urls), path("accounts/", include("allauth.urls")), path("", Home.as_view(), name="home"), # new
]

That's it! Django Allauth is configured and ready to test. You should now be able to log in via username and password. Run the server. Navigate to http://127.0.0.1:8000/accounts/login/. Make sure you can log in with your superuser credentials.

You'll probably want to override the default templates to apply CSS style and what not. Review the Templates page from the official docs for more.

GitHub Provider

Now that both Django and Django Allauth are ready let's wire up our first social auth provider -- GitHub.

App

First, we need to create an OAuth app and get the OAuth keys from GitHub. Log in to your GitHub account, and then navigate to https://github.com/settings/applications/new to create a new OAuth application:

Application name: Testing Django Allauth
Homepage URL: http://127.0.0.1:8000
Callback URL: http://127.0.0.1:8000/accounts/github/login/callback

register github oauth app

Click "Register application". You'll be redirected to your app. Take note of the Client ID and Client Secret:

github oauth ap

If a Client Secret wasn't generated, click "Generate a new client secret".

Next, we need to add the GitHub provider in the Django admin panel.

Run the server:

(.venv)$ python manage.py runserver

Log in to the admin at http://127.0.0.1:8000/admin. Then, under "Social applications", click "Add Social Application":

  • Choose GitHub as the Provider
  • Add a name
  • Add the Client ID and Client Secret (to Secret key) obtained earlier
  • Add example.com as one of the Chosen Sites

django admin github oauth provider setup

We've successfully integrated GitHub as a social auth provider. With that, let's update the templates/home.html template to test it out:

{% extends '_base.html' %} {% load socialaccount %} {% block content %} <div class="container" style="text-align: center; padding-top: 10%;"> <h1>Django Social Login</h1> <br /><br /> {% if user.is_authenticated %} <h3>Welcome {{ user.username }} !!!</h3> <br /><br /> <a href="{% url 'account_logout' %}" class="btn btn-danger">Logout</a> {% else %} <!-- GitHub button starts here --> <a href="{% provider_login_url 'github' %}" class="btn btn-secondary"> <i class="fa fa-github fa-fw"></i> <span>Login with GitHub</span> </a> <!-- GitHub button ends here --> {% endif %}
</div> {% endblock content %}

Run the app. You should now be able to log in via GitHub.

django github social auth

After logging in, you should see the user at http://127.0.0.1:8000/admin/auth/user/ as well as the associated social account at http://127.0.0.1:8000/admin/socialaccount/socialaccount/. If you view the social account, you'll see all the public data associated with the GitHub account. This data (which is called scope) can be used for your user profile on Django. It's recommended to use a custom User Model for this. For more, review Creating a Custom User Model in Django.

Do you need to read or write access to user info beyond Allauth's default scope? Review Changing provider scopes from the official docs.

Twitter Provider

Setting up the Twitter provider is similar to GitHub:

  1. Create an OAuth app on Twitter
  2. Register the provider in the Django admin
  3. Update the home.html template

Start by applying for a Twitter developer account. Once created, navigate to Projects and Apps and click "Create App".

Give the app a name, and take note of the API key and API secret key. Then, under "Authentication Settings". Enable "Enable 3-legged OAuth" and "Request email address from users". Add the Callback, Website, Terms of service, and Privacy policy URLs as well:

Callback URL: http://127.0.0.1:8000/accounts/twitter/login/callback
Website URL: http://example.com
Terms of service: http://example.com
Privacy policy: http://example.com

register twitter oauth app

Let's add the provider in the Django Admin.

Run the server:

(.venv)$ python manage.py runserver

Log in to the admin at http://127.0.0.1:8000/admin. Then, under "Social applications", click "Add Social Application":

  • Choose Twitter as the Provider
  • Add a name
  • Add the API key (to Client id) and and API secret key (to Secret key) obtained earlier
  • Add example.com as one of the Chosen Sites

django admin twitter oauth provider setup

Remember to safeguard your API keys and tokens.

Finally, add a "Login with Twitter" button to templates/home.html:

{% extends '_base.html' %} {% load socialaccount %} {% block content %} <div class="container" style="text-align: center; padding-top: 10%;"> <h1>Django Social Login</h1> <br /><br /> {% if user.is_authenticated %} <h3>Welcome {{ user.username }} !!!</h3> <br /><br /> <a href="{% url 'account_logout' %}" class="btn btn-danger">Logout</a> {% else %} ... <!-- Twitter button starts here --> </a> <a href="{% provider_login_url 'twitter' %}" class="btn btn-primary"> <i class="fa fa-twitter fa-fw"></i> <span>Login with Twitter</span> </a> <!-- Twitter button ends here --> {% endif %}
</div> {% endblock content %}

Navigate to http://127.0.0.1:8000 to test out the auth workflow.

Conclusion

This tutorial detailed how to set up social auth with Django and Django Allauth. You should now have a solid understanding of how to wire up new social auth providers:

  1. Add the appropriate Allauth app to INSTALLED_APPS in the settings file
  2. Create an OAuth app on the provider's developer site and take note of the tokens/keys/secret
  3. Register the app in the Django Admin
  4. Add the URL to the template

Although this tutorial focused on Django Allauth, it doesn't necessarily mean it should be used over Python Social Auth in every scenario. Explore both packages. Try implementing custom forms and linking multiple social accounts.

Grab the code from django-social-auth repository on GitHub.