Django Authentication with Facebook

It can take a long time to create and log in to website accounts on the internet manually. Social authentication solves this difficulty in modern web apps by allowing 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.

The development of procedures, sometimes known as apps on third-party sites like Facebook, Twitter, Github, and Google, allows users to re-use their identity to access other resources. The latter concept is known as social authentication – in our instance, it is through Django applications.

This feature is convenient in Django projects because it allows users to register with just a few clicks rather than going through a lengthy process.

Users authorizing tokens are then exchanged between third-party sites and the asking party, your Django application, to display a user’s authorization in social authentication systems at their most basic level.

The asking party, i.e., the Django application, can also request basic user information, for instance, users’ email address and more specific information, e.g., a user’s Facebook friends from the third-party site, depending on the application and its settings.

Django Authentication with Facebook

We’ll build a Django application that allows users to sign in using their Facebook account in this post.

Creating Django Application

1) mkdir facebook_login && cd facebook_login


2) virtualenv facebook_env

create virtual environment Django
create virtual environment Django

3) source facebook_env/bin/activate

activate virtual environment
activate virtual environment

3) pip install Django==3.2.6

install Django using pip
install Django using pip

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

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

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

7) python manage.py migrate

run migrations
run migrations

8) python manage.py runserver

run DjangoFacebookLogin application using runserver
run DjangoFacebookLogin application using runserver

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, social authentication and simple flows.

Django-allauth supports a variety of social providers. Each social provider has its package that needs to be added to the list of INSTALLED_APPS in settings.py.

We will start by installing Django-allauth by running the following command:

pip3 install django-allauth

First, we will add our newly created app, facebook_login, as follows.

'facebook_login',

Then we will proceed to add the following apps under INSTALLED_APPS in settings.py, as shown below.

django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',

At the bottom of settings.py, add the following lines of code.

# site id
SITE_ID =2

# some options for your page's signup.

ACCOUNT_EMAIL_REQUIRED=True
ACCOUNT_USERNAME_REQURIED=True
LOGIN_REDIRECT_URL = "/"

If you succeed in login in, you’ll be redirected to the main page.

Configuration of Authentication Classes in Django

Django keeps a list of “authentication backends” that it examines during user authentication behind the scenes. Django tries the second authentication method if the first fails, and so on until all backends have been tried.

The AUTHENTICATION_BACKENDS array contains a list of authentication backend classes (as strings), and it defaults to:

['django.contrib.auth.backends.ModelBackend']

To allow authentication with the social platforms, we’ll be looking at in this article, we can change it and add new authentication classes.

AUTHENTICATION_BACKENDS = (
  'allauth.account.auth_backends.AuthenticationBackend',
  'django.contrib.auth.backends.ModelBackend',
)

In addition, add the following in your settings.py files, preferably at the bottom.

SOCIALACCOUNT_PROVIDERS = {'facebook': {}, 'google':{}, 'twitter':{}}

The SOCIALACCOUNT _PROVIDERS variable is a dictionary of keys that correspond to each social provider. Each key contains an empty dictionary value that will be filled with provider-specific configuration choices in the future. Next, we explore setting up Facebook social providers and filling in these configuration parameters as shown.

SOCIALACCOUNT_PROVIDERS = \
{'facebook':
{'METHOD': 'oauth2',
'SCOPE': ['email','public_profile', 'user_friends'],
'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
'FIELDS': [
'id',
'email',
'name',
'first_name',
'last_name',
'verified',
'locale',
'timezone',
'link',
'gender',
'updated_time'],
'EXCHANGE_TOKEN': True,
'LOCALE_FUNC': lambda request: 'kr_KR',
'VERIFIED_EMAIL': False,
'VERSION': 'v2.4'}}

You’ll also need to add a social provider’s application credentials as ‘Social applications’ model records through the Django admin, in addition to the configuration settings in SOCIALACCOUNT_PROVIDERS.

Update URLs

We need to modify our urlpatterns to enable us to log in, log out, and authenticate using Facebook OAuth 2. As a result, we will add the following code to our urlpatterns.

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

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

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.

import os

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

Create a new urls.py for the newly created app

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

# facebook_login/urls.py

from django.urls import path
from .views import view_name

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

Add URL to app’s to urls.py

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 created 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

Adding Static Files and Templates

Let’s move on to something visible now that we’ve finished setting up and configuring the application. This section will create the groundwork for the templates that will be used to display the application.

Let’s make a new folder in the core directory, which we’ll call templates:

create new templates under facebook_login/templates/

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

mkdir facebook_login/templates/

Then, create a templates file called home.html

touch facebook_login/templates/home.html

Then update home.html as follows,

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

{% load socialaccount %}
<html>

<head>
    <title>Facebook Registration</title>
</head>

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

    {% else %}

    <a href="{% provider_login_url 'facebook' %}">Login with Facebook</a>
    {% endif %}

</body>

</html>

Styling

If you need some styles to make your code appear lovely when it’s rendered, all you need is to create a static folder in the root of the core folder where you’ll keep your styles.

Create a folder called CSS within the static directory, and then a file called index.css within the CSS folder.

Open the index.css file and add your CSS code to it as follows:

.social-container {
display: flex;
flex-direction: column;
justify-content: center;
}
.btn a, .btn a:hover {
color: white;
text-decoration: none ;
}

In this demo, however, we will not be styling our application. But, it is something worth exploring if you intend to take your application to another level.

Create a View function

In our facebook_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. In this case, it will render the home.html page.

from django.shortcuts import render
from django.contrib.auth.decorators import login_required

# Create your views here.
from django.shortcuts import render

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

Add Facebook OAuth 2 to Django


In our Django admin, we need to register our site ID and Social application. First, we will create a superuser, migrate and start the server.

Creating a Super User for your Django App

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.

create a super user for your Django app
create a super user for your Django app
python3 manage.py migrate
python3 manage.py runserver

Replace the given site, example.com to http://localhost:8000/, or if you’re currently in production, you can use the IP or domain name of your page. Then, we will proceed to make further changes by adding Facebook as a social application with the necessary configurations as represented in the image below.

adding Facebook as a social application in Django app
adding Facebook as a social application in the Django app

We are now ready to log in using Facebook after saving the program.

Put these templates elements at the beginning of any HTML page where you want users to log in. In our case, this is home.html

{% load socialaccount %}
{% providers_media_js %}

Then, you can specify the exact location where you intend to place your login button, as shown below.
The first case will apply if you are using JavaScript SDK.

<a href="{% provider_login_url ">Login Button image</a>

In addition, you can add the following piece of code after the application button.

<a href="{% provider_login_url ">Sign in with Facebook</a>

Registering our Facebook OAuth 2 App

The initial step is to identify the kind of app you want to create. In our case, we will create a consumer app as shown below.

select  consumer as the app type
select consumer as the app type

The consumer app allows us to connect consumer products and permissions, for instance, Facebook Login, to our app. After selecting a consumer, we will proceed to the next window, which will specify our app’s name.

name the app DjangoAuth2
name the app DjangoAuth2

We will create our Facebook app and give it the name DjangoAuth2 as shown in the diagram above. Then, we will click on “Create App” to finalize the app creation process.

The next step is to create a test app for our DjangoAuth2 application. We will give it the name DjangoAuth2 – Login, as shown in the image below.

create a test app for your DjangoAuth2 application

create a test app for your DjangoAuth2 application

We will then proceed to edit details of our test version of DjangoAuth2 by providing the domain and the site URL as shown.

edit details of our test version of DjangoAuth2

edit details of our test version of DjangoAuth2

We will then save the changes before continuing with our setup process. After creating your app, you should fetch the App ID and the Secret Key as they are critical in the authentication process.

#facebook
SOCIAL_AUTH_FACEBOOK_KEY = 'secret!'  # App ID
SOCIAL_AUTH_FACEBOOK_SECRET ='secret!' #app key

Testing Django Authentication with Facebook

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

A page similar to the following will appear if you login successfully.

Successfull Login
Successful Login

In some cases, your configurations may not be right and you may simply need to look over again to ascertain that this is OK. A common error in case of such a mismatch is, “Facebook has detected that CodeLogin isn’t using a secure connection to transfer information”. Below is a case that we encountered when we attempted to use ngrok in our configuration.

Facebook has detected an error
Facebook has detected an error

Information on the logged-in User

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

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

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

Simply write the following in your template to view this user information.

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 }}

Complete Code for important sections of the application

# settings.py

"""
Django settings for DjangoFacebookLogin 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-pytfqn=1(z53vns-%!e52&5qyf^)p#mf65$4c$nrd03(bh=)xy'

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

    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.facebook',
]

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 = 'DjangoFacebookLogin.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 = 'DjangoFacebookLogin.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'

#site id
SITE_ID =4
#little options for your page's signup.
ACCOUNT_EMAIL_REQUIRED=True
ACCOUNT_USERNAME_REQURIED=True


LOGIN_REDIRECT_URL = "/" 
#if you succeed in login, you'll be redirected to the main page.

AUTHENTICATION_BACKENDS = (
    'allauth.account.auth_backends.AuthenticationBackend',
    'django.contrib.auth.backends.ModelBackend',
)

SOCIALACCOUNT_PROVIDERS = \
    {'facebook':
       {'METHOD': 'oauth2',
        'SCOPE': ['email','public_profile', 'user_friends'],
        'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
        'FIELDS': [
            'id',
            'email',
            'name',
            'first_name',
            'last_name',
            'verified',
            'locale',
            'timezone',
            'link',
            'gender',
            'updated_time'],
        'EXCHANGE_TOKEN': True,
        'LOCALE_FUNC': lambda request: 'kr_KR',
        'VERIFIED_EMAIL': False,
        'VERSION': 'v2.4'}}


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

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

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

from django.shortcuts import render

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

Conclusion

We’ve completed this tutorial and learned how to set up Facebook authentication in Django with minimal settings using the Django-allauth package. We also learned how to set proper configurations on the Facebook Setup page, including creating a test app for our DjangoAuth2 app. We also added a domain as localhost and website URL as http://localhost:8000. Further, we also looked at how to add the App ID and secret key to our Django application which is at the center of this integration.

The relevance of Facebook authentication and social authentication in modern web applications cannot be overstated, as we highlighted at the outset of this article. We hope you found this article helpful and will use this concept in your upcoming projects.

Similar Posts

2 Comments

Leave a Reply

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