Django Authentication with Google

Manually creating and logging into accounts on the internet can be time-consuming. Social authentication, a mechanism for users to sign in (and sign up) with an application using login information from a social network provider with which they already have an account, solves this problem in modern web applications.

Social authentication entails the creation of workflows (also called apps) on third-party sites (e.g., Facebook, GitHub, Google, Twitter) that allow users to re-use their identity to access external resources (in our instance, Django applications). This functionality is helpful in Django apps because it allows users to register with just a few clicks rather than a lengthy registration procedure.

At their most basic level, social authentication systems include users authorizing tokens, which are subsequently exchanged between third-party sites and the requesting party (your Django application) to display a user’s authorization.

In addition, depending on the application and its setup, the requesting party (i.e., the Django application) can request basic user information (e.g., email) as well as more detailed information (e.g., a user’s Facebook friends) from the third-party site.

Django Authentication with Google

This article will create a Django application that allows users to sign in using their Google account.

Creating Django Application

We will create a new Django application from scratch for this application. Below are the steps to follow.


1) mkdir dev && cd dev


2) virtualenv google_env

create a virtual environment
create a virtual environment

3) source google_env/bin/activate

activate virtual environment
activate virtual environment

3) pip install Django==3.2.6

install Django
install Django

4) Create a new Django project (django-admin startproject DjangoGoogleLogin)

5) Navigate to the newly created project(cd DjangoGoogleLogin)

6) Start a new Django app (python manage.py startapp google_login)

7) python manage.py migrate

run migrations
run migrations

8) python manage.py runserver

runserver
runserver

Upon successful running, you should be able to navigate to http://127.0.0.1:8000, where you will view an instance of your Django application as follows.

Project Configuration

First, we will add our newly created app in the INSTALLED_APPS under the settings.py. It is a standard procedure to install your newly created app in your project. You do this in your settings.py under the section INSTALLED_APPS as shown below.

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'google_login',
]

By adding this new line of code, your project knows the existence of our newly created app.

Specify the path of the template under TEMPLATES

In the settings.py, locate TEMPLATES, then make the following modifications

{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['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',
],
},
},
]

Add both the media and static folders in STATIC_ROOT

In your settings.py, add the following set of lines.

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Update urls.py

At this point, you can update urls.py with your desired URL for the newly created app

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

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

Create a new urls.py for the newly created app

Now, we need to create a urls.py in the google_login app as follows:

# google_login/urls.py
from django.urls import path
from .views import view_name

urlpatterns = [
path('', view_name, name="view_name"),
]

The urls.py module helps us to include our URL configuration for our newly created app. In addition, we need to hook up the URLs to enable us to visit the page we completed recently.

What happens is that any URLs defined in urls.py are registered when you visit the URL’s root path, which is localhost:8000.

Make APP Setting Configurations

create new templates under google_login/templates/

We will require an HTML template that will interact with the view function to display information to the user.
first, create a templates directory under the new app

mkdir google_login/templates/

Then, create a templates file called home.html

touch google_login/templates/home.html

Create a View function

In our google_login app, let’s create a view function in views.py. Recall that views are classes or a collection of functions in views.py found in our app directory.

Each function or class deals with a specific logic and is usually processed when the said URL is visited.

from django.shortcuts import render

def view_name(request):
  return render(request, 'home.html', {})

Django-allauth

What is the purpose of Django-allauth?

Django-allauth is an authentication module for Django. It handles authentication, registration, account management, and 3rd party (social) account authentication – an integrated set of Django apps. It comes with a fully integrated authentication software that supports both local and social authentication and simple flows.

how to install Django-allauth

Run the following command to install Django-allauth

pip3 install django-allauth

How to configure Django-allauth

Django-allauth settings.py is used to configure Django-allauth.
After installing the package, add django-allauth to INSTALLED_APPS in settings.py to register it. Essentially, you can include any of the providers you need to register. The updated INSTALLED_APPS should appear as follows:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites', # Add this
 
 # Add the following django-allauth apps
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.google',
# ...
]




Also, add the following allauth configuration settings and backend settings at the bottom of the settings.py.

AUTHENTICATION_BACKENDS = [
  'django.contrib.auth.backends.ModelBackend',
  'allauth.account.auth_backends.AuthenticationBackend'
]

In addition, you also need to add the SITE_ID and also specify the redirect URL. The latter will be helpful when the user logs in successfully. Other configuration settings can also be added as below.

SITE_ID = 1
LOGIN_REDIRECT_URL = '/'

Additional configuration settings

SOCIALACCOUNT_QUERY_EMAIL = True
ACCOUNT_LOGOUT_ON_GET= True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_REQUIRED = True

Further, users’ email addresses can be received upon a successful login if the email scope is enabled. It can be done with the following configurations.

SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
        ],
        'AUTH_PARAMS': {
            'access_type': 'online',
        }
    }
}

urls.py

Add the allauth urls to the urls.py file in your project directory and import include at the top. We create the /accounts route, which contains all Django-allauth URLs. This route will be used for all OAuth activities.

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

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

Creating a SuperUser in Django

We will create a superuser for our Django application by running the following command on the terminal.

$ python manage.py createsuperuser

Subsequently, we will fill in the required details that comprise the username, the email address, and both a password and a confirmation of the same.

createsuperuser
createsuperuser

Setting up Google APIs

First, we will need to set up an OAuth application in Google Developers Console to add Google login to our app.

The starting point is creating a new Google APIs project in the Google Developer APIs Console. To accomplish this, we will access the dashboard so that we can create the new project.

We will give our new project a name, preferably the name of our website or app. When we send users to the Google login page, they will see this project name. In our case, we will name it, DjangoGoogleLogin. Then, we will proceed by clicking on ‘Create.’

Django Google Login APP
Django Google Login APP

NOTE: All we need is a Google APIs project and a complete Client ID and Client Secret.

Go to the OAuth Consent Screen and register your app

Fill out the OAuth consent screen to register your app. Under ‘Developer contact information,’ you need to submit ‘App name,’ ‘User support email,’ and ‘Email addresses.’ To save and continue, click the ‘Save and Continue button’.

Creating new API Credentials

We will click on the ‘Create Credentials’ button under Credentials at the very top section on the dashboard. Subsequently, we will select the option ‘OAuth Client ID’ alternative.

We will then provide the following URIs under the section ‘Authorized Javascript origins’:

http://localhost:8000
http://127.0.0.1:8000

Then, we will add the following URIs under ‘Authorized redirect URIs’:

http://127.0.0.1:8000/accounts/google/login/callback/
http://localhost:8000/accounts/google/login/callback/

The above URIs are almost similar because the Django application is accessible through 127.0.0.1:8000 or localhost:8000. Only remember to update the URIs to the given domain name once the app is in production.

Now, note down the Client ID and the Client Secret. Those can be found on the left-hand side of the page.

Adding Google OAuth 2 Credentials to Django App

First, we will run the application by using the following command.

python manage.py runserver

We can now access the site using any of the following links, http://127.0.0.1:8000/admin or http://localhost:8000/admin. The latter will enable us to access the Django admin page for our DjangoGoogleLogin app.

We will fill in the necessary details that comprise a Domain name and a Display name under the section sites. For each, we will populate with localhost:8000 and 127.0.0.1:8000.

These are not fixed either. You could have a different site for your application, for instance, ‘example.com,’ or by using whatever appealing name that resonates with you. Just remember to add this under the sites, as shown in the image below.

add site in the admin page
add site in the admin page

Next, we will populate the following fields under the social applications. To enable this, you need to click add. You will need to fill the following:

  • provider: Google
  • Name
  • Client ID
  • Secret Key
  • In the available sites, choose your sites and use the right-facing arrow to move it to the section named ‘Chosen sites.’

Add Google under social application
Add Google under social application

Remember that we are currently logged in as the system admin. So, we will need to log out to attempt to authenticate using our Google account.

More often than not, you will get the following error: ‘SocialApp matching query does not exist at http://127.0.0.1:8000/accounts/google/login/. That implies that the site ID created in the Django admin is not like the one in settings.py.

SocialApp matching query does not exist
SocialApp matching query does not exist

Also, it could be because an ‘example.com’ site is already created for you by Django, especially when the project is not new. The solution to this is to delete the later entry from the Sites admin page. Then, make changes to the SITE_ID in settings.py to the expected ID. On the other hand, you could also play with the value of SITE_ID, like setting it to 4 or 3.

Testing Authentication with your Google Authentication

The template for this purpose will consist of the following details:

{%% load socialaccount %%}
<html>

<head>
    <title>Google Registration</title>
</head>

<body>
    <h1>My Google Login Project</h1>
    {%% if user.is_authenticated %%}
    <p>Welcome, {{ user.username }} !</p>

    {%% else %%}
    <h1>My Google Login Project</h1>
    <a href="{%% provider_login_url 'google' %%}">Login with Google</a>
    {%% endif %%}

</body>

</html>

Access the home page at the link, http://127.0.01:8000/. Here, there will be a button prompting you to sign in with the Google login, which should redirect you to the Google login page to log in or authorize the app in case you are already logged in to your Google account.

Django Google Authentication Admin
Django Google Authentication Admin

When the Authentication is successful, you should be in a position to see the following welcome screen with your name mentioned – of course, that is the name registered on your Google account. In our case the name is masa.

welcome screen after successful Authentication
welcome screen after successful Authentication

Information on the logged-in User

You can check the user information collected from Google at http://127.0.0.1:8000/admin/socialaccount/socialaccount/ after signing in with Google.

Google doesn’t provide much information about its users. Your app must be verified to receive more user data from Google.

For individuals that signed up with their social account, a SocialAccount model instance is offered.

Simply write the following in your template:

Avatar URL: {{ user.socialaccount_set.all.0.get_avatar_url }}
UID: {{ user.socialaccount_set.all.0.uid }}
Date Joined: {{ user.socialaccount_set.all.0.date_joined}}
Last Login: {{ user.socialaccount_set.all.0.last_login}}
Full Name: {{ user.socialaccount_set.all.0.extra_data.name }}

Here is the complete code for most sections to help you follow through easily:

# settings.py

"""
Django settings for DjangoGoogleLogin project.

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

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
import os

# 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-w27&t$h@(d6cvpby!2#u-26y8r7%%ex0_w&v*5_=b7g5+=09ex='

# 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',
    'google_login',

    'django.contrib.sites', # Add this

    # Add the following django-allauth apps
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google', 
]

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 = 'DjangoGoogleLogin.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['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 = 'DjangoGoogleLogin.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'

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend'
]


SITE_ID = 3
LOGIN_REDIRECT_URL = '/'

# Additional configuration settings
SOCIALACCOUNT_QUERY_EMAIL = True
ACCOUNT_LOGOUT_ON_GET= True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_REQUIRED = True


SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': [
            'profile',
            'email',
        ],
        'AUTH_PARAMS': {
            'access_type': 'online',
        }
    }
}

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

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

# views.py

from django.shortcuts import render

def view_name(request):
    return render(request, 'home.html', {})

Conclusion

Overall, we’ve been successful in using Google to authenticate users in our Django application. While this guide only looks at Google’s OAuth 2.0 authentication, you may use Django-allauth to incorporate other OAuth providers as well.

We hope that you will be able to use it in your future projects.

Similar Posts

Leave a Reply

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