Django authentication with GitHub

The process of manually signing up and signing into your account for web applications can be very strenuous. As a result, social-media authentication has come in handy to ease the entire process by using login information from one of your favorite social networks.

OAuth providers such as Google, Facebook, and GitHub do comprehensive checks to prevent unwanted access to their services; using social auth rather than developing your auth system can improve the security of your app. Thus, a third-party OAuth provider handles the web application’s authentication; you won’t need to do so.

Django authentication with GitHub

In this article, we will delve into using Github to authenticate users into their accounts.

OAuth

One of the implementations of OAuth is social auth. OAuth is a standardized protocol for authorization that is open. It works by allowing third-party auth providers to carry out the verification of the user’s identity. As a result, the typical flow of the entire process is as follows.

Step 1: User tries to log in to your application using their third-party application account, for instance, Twitter or Github. The third-party application is responsible for the authentication.

Step 2: The user is then redirected to the third-party authentication provider for purposes of verification.

Step 3: Once the user is authenticated, they are then redirected to your application.

Step 4: Now, they will be logged in to your application and have access to resources that have been protected.

Why use OAuth?

  1. The overall security is advanced.
  2. The flow process is seamless, with users not needing to create usernames or passwords. Thus, it is not only faster but easy.
  3. On the off chance of an attempted security breach, there will be no third-party damage because of the passwordless authentication.

Challenges of Using OAuth

  1. Many people usually ignore requested OAuth providers’ permissions.
  2. If a user doesn’t have an account with any of the OAuth providers, it will be impossible to access your application if you do not have a custom username and password. So, it would be good to have both so that the user has an alternative option to access your application.
  3. It means that your web application is entirely dependent on the third-party OAuth provider, which limits your control by a more significant margin. For instance, if the said app is experiencing technical hitches, that is beyond your control.

Is Django Allauth better than Python Social Auth?

Two primary packages are popular when implementing social authentication in Django. These comprise Python Social Auth and Django Allauth. Without exploring the two packages separately, it isn’t straightforward to tell which one is better than the other. However, we will look at the differences in terms of their pros and cons in the following section.

Pros for Python Social Auth

  1. It has a broader coverage supporting various frameworks like Flask, Django, Tornado, Pyramid, and Webpy.
  2. It has a storage interface that enables you to add more ORMs. For instance, it determines how the storage interface works with SQLAlchemy ORM.
  3. Over 50 OAuth providers are supported.
  4. It supports both MongoEngine ODM and Django ORM.

Cons of Python Social Auth

  1. There are about 114 open issues on Github as of the time this article was written.
  2. An initial setup is needed to register OAuth service providers, which can challenge newbies.
  3. The documentation is more straightforward and could be improved by re-looking the organization of some of the work.

Pros of Django Allauth

  1. It simplifies and eases the process of customizing forms used in the auth flow.
  2. Besides providing regular auth, it also has authentication with both a username and a password.
  3. Django Allauth supports over 50 authentication providers.
  4. Among the popular Django packages is Django Allauth.

Cons of Django Allauth

  1. As of this writing, there are about 326 open issues on Github.
  2. It can be challenging for beginners initially since the OAuth provider needs some initial setup.
  3. The documentation is structured in a complex manner, making it difficult for beginners to cope.

Creating Django Application(CodeLogin)

We will start by creating a virtual environment and installing Django.

  1. mkdir django-github-auth && cd django-github-auth
  2. virtualenv github_env
create a virtual environment
create a virtual environment
  1. source github_env/bin/activate
activate virtual environment
activate virtual environment
  1. pip install Django==3.2.6
install Django using pip
install Django using pip

At this point, we will now create a new app then apply the migrations. Finally, we will run the server.

  1. django-admin startproject CodeLogin_app
start a new project called CodeLogin_app
start a new project called CodeLogin_app
  1. python manage.py migrate
run migrations
run migrations
  1. python manage.py runserver
run server
run the server

When you access the URL http:127.0.0.1:8000 the following screen should be visible.

Django Default Page
Django Default Page

Django Allauth configuration

The next step is to set up Django Allauth for our Codelogin application. To do so, let’s install Django-allauth using pip as follows.

pip install django-allauth==0.45.0
install django-allauth using pip
install django-allauth using pip

We will then modify the INSTALLED_APPS in the settings.py by adding allauth apps. If we do not do this, Django Allauth will not work with our Codelogin app. The new changes should appear as follows.

# CodeLogin_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",
  
# allauth apps
"allauth", # new
"allauth.account", # new
"allauth.socialaccount", # new
# github
"allauth.socialaccount.providers.github", # new
]

Initially, we added the Django “sites” framework to enable Allauth to work as expected. Then we added the primary Allauth apps that comprise allauth, allauth.account, and allauth.socialaccount.

After that, we will add the following set of code at the bottom of the settings.py

# CodeLogin_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

The above section defines several parameters that we will define below:

Allauth defines the authentication backend that ensures that all the login and logout through the regular username and password or OAuth is now handled by Allauth.

ACCOUNT_EMAIL_VERIFICATION =” none” is responsible for turning off email verification because it is unnecessary now. It is because Django does a workflow setup for its email verification.

LOGIN_REDIRECT_URL=” home” is responsible for directing the user to the homepage after successful authentication.

ACCOUNT_LOGOUT_ON_GET=True ensures that the confirm logout page is skipped by directly logging out the user when the logout button is clicked through a GET request.

SITE_ID – is needed for Django Allauth to work correctly.

Update urls.py

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

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

That will include Django Allauth. In addition, we need to apply the migrations associated with Django Allauth by running the following command.

python manage.py migrate

Do not to forget the above step because Django Allauth needs the new tables.

Creation of Templates

In this section, we will create templates for our application to help communicate the process happening in the application.
First, we will create a “templates” directory in the base directory and two other files, namely, home.html and base.html.

mkdir templates && cd templates
touch _base.html home.html

We will then update the path of the template on the settings.py to make it easier for Django to find the templates. The new changes should appear as follows.

#CodeLogin_app/settings.py

TEMPLATES = [
{
…
"DIRS": [str(BASE_DIR.joinpath("templates"))],
…
},
]

Then also make the following changes to the two template files as follows:

<!-- templates/base.html:-->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/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 GitHub Authentication</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 GitHub Authentication</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 %}

Next, we will create a view to serve the templates we have created above. Inside the view.py file, add the following code.

# CodeLogin_app/views.py

from django.views.generic import TemplateView


class Home(TemplateView):
  template_name = "home.html"

We will then create a new URL so that the final look of the urls.py is shown below.

# CodeLogin_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
]

Creating superuser credentials

To create a superuser for our CodeLogin application, we will run the following command and pass in the required details, including the username, email address, a designated password, and a confirmation.

$ python manage.py createsuperuser

We are not done with setting up the Django Allauth and doing the configurations as well. Now, we are super ready to test. You should be able to run the application and log in using a username and a password. In our case, we will use the credentials we created in the section above while examining superuser credentials. To access the login page, you can access the following link, http://127.0.0.1:8000/accounts/login/.

Note that you can also make changes to the CSS stylesheets to make your application more appealing to the user. In addition, you may also choose to make changes to the default templates.

GitHub OAuth Provider

After ensuring that you have successfully set up your Django and Django Allauth, now it’s time to set up a GitHub OAuth provider.
The starting point is to create an OAuth app and fetch the OAuth ID and Keys from GitHub.
First, log in to your GitHub account, then go to the settings section(in the drop-down menu from your profile that appears when you click on the down-facing arrow.).
Then click on the developer settings where you have three options at your disposal:

  • GitHub Apps
  • OAuth Apps
  • Personal access tokens

Our concern is the OAuth Apps. Herein, click on New OAuth App and fill the necessary fields as shown in the image below.

GitHub registering a new OAuth App
GitHub registering a new OAuth App

After clicking on “Register application,” you will be taken to your app, where you should carefully note both your client secret and client ID.

CodeLogin Client ID and Client Secrets
CodeLogin Client ID and Client Secrets

The next step will be to register Github OAuth credentials in our CodeLogin administrator panel. First, ensure that your application is running. If it is not, then do so by running the following command.

python manage.py runserver

So, we will need to access the admin panel by using the link, http://127.0.0.1:8000/admin, and you should have a page similar to this after you login successfully.

admin dashboard
admin dashboard


We will start by adding a site to our Django application under the category SITES. We will add 127.0.0.1:8000 to both the Domain name and the Display name as follows.

add a new site
add a new site

Subsequently, click on “Add Social Application” and fill the empty fields under the social applications.

  • Select GitHub as the Provider
  • Add a Customized name
  • Add the Client ID and Client secret you noted from the previous section.
  • Then, add 127.0.0.1 as one of the selected sites.

After filling all the sections, it should appear as in the diagram below.

Add Django as a new social application
Add Django as a new social application

Finally, we will update the home page template as shown below.

 <!-- CodeLogin_app/templates/home.html -->

{% extends 'base.html' %} {% load socialaccount %}

{% block content %}

<div class="container" style="text-align: center; padding-top: 10%;">
  <h1>Django Authentication with GitHub</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 code 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 code ends here -->
  {% endif %}
</div>

{% endblock content %}

Now, we are ready to run and log in via GitHub.

Login with GitHub

We first need to access the homepage for our Django authentication application by using the following address http://127.0.0.1:8000. If you are OK, you should be able to see a page similar to this.

After clicking on the button “Login with GitHub,” you will be redirected to GitHub’s Login page with a clear indication that you need to sign in to GitHub to proceed to CodeLogin is our Django application.

sign in to GitHub to continue to CodeLogin
sign in to GitHub to continue to CodeLogin

In the next window, you are required to provide an authentication code sent to your email if you have enabled two-factor authentication in your account.

Provide Device Verification if you have enabled two-factor authentication in your account
Provide Device Verification if you have enabled two-factor authentication in your account

When you can provide the correct verification code, you will be redirected to the homepage for your Django application with a Welcome message appended to your GitHub username, as indicated in the diagram below.

Successfully logged in using GitHub
Successfully logged in using GitHub

After login in, go to http://127.0.0.1:8000/admin/auth/user/ to see the user, then go to http://127.0.0.1:8000/admin/socialaccount/socialaccount/ to see the related social account.

social account related to the authenticated user
social account related to the authenticated user

You can access all of the public data associated with the GitHub account if you go to the social account.
This data (known as scope) can be used in your Django user profile. For that reason, it’s best to utilize a custom User Model.

Complete Code for your reference

# CodeLogin_app/settings.py

"""
Django settings for CodeLogin_app project.

Generated by 'django-admin startproject' using Django 3.2.8.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-p**t!$vt*5@42-t6iwgbrc%)*x*)2-fl^(94a=&=0g)_1_v6up'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "django.contrib.sites",

     # allauth apps
    "allauth", # new
    "allauth.account", # new
    "allauth.socialaccount", # new
    # github
    "allauth.socialaccount.providers.github", # new

]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'CodeLogin_app.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        "DIRS": [str(BASE_DIR.joinpath("templates"))],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'CodeLogin_app.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL = '/static/'

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

# social_app/settings.py

AUTHENTICATION_BACKENDS = (
    "allauth.account.auth_backends.AuthenticationBackend",
)

SITE_ID = 2
ACCOUNT_EMAIL_VERIFICATION = "none"
LOGIN_REDIRECT_URL = "home"
ACCOUNT_LOGOUT_ON_GET = True
# CodeLogin_app/views.py

from django.views.generic import TemplateView


class Home(TemplateView):
    template_name = "home.html"

# CodeLogin_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
]

<!-- CodeLogin_app/templates/base.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/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 GitHub Authentication</title>
  </head>
  <body>
    {% block content %} {% endblock content %}
  </body>
</html>
 <!-- CodeLogin_app/templates/home.html -->

{% extends 'base.html' %} {% load socialaccount %}

{% block content %}

<div class="container" style="text-align: center; padding-top: 10%;">
  <h1>Django Authentication with GitHub</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 code 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 code ends here -->
  {% endif %}
</div>

{% endblock content %}

Conclusion

This article has illustrated how to use Django and Django Allauth to build up GitHub social authentication. In addition, it would help if you have a firm grasp of setting up new social authentication with GitHub as your provider.

The key takeaways include adding the necessary Allauth apps to INSTALLED_APPS in the settings file, making an OAuth app on GitHub’s developer site, keep track of the tokens, keys, and secrets. Finally, remember to integrate the two by creating a site and GitHub social application on your Django application’s Admin page.

Although this lesson focuses on GitHub social applications, Django Allauth can integrate other social applications like Twitter, Google, and Facebook.

That’s it! If you have any questions, reach out through the comments sections.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *