episyche logo

Episyche

React/Single sign-on (SSO)/

How to configure LinkedIn SSO in Django Rest Framework with React?

Published on

How to configure LinkedIn SSO in Django Rest Framework with React?
Single Sign On (SSO) to give your users convenient but secure access to all their web applications with a single set of credentials.This guide explains how we can configure LinkedIn SSO(Social Login) in Django Rest Framework backend with a React.

Introduction :

Django (Django rest Framework):

Django REST framework (DRF) is a powerful and flexible toolkit for building Web APIs.Its main benefit is that it makes serialization much easier. Django REST framework is based on Django's class-based views, so it's an excellent option if you're familiar with Django. To know more about relative links click here

Node.js :

Node.js is an open-source, cross-platform, back-end JavaScript runtime environment that runs on a JavaScript Engine and executes JavaScript code outside a web browser. and NPM is a package manager for Node. js packages. The NPM program is installed on your computer when you install Node.js. To know more about relative links click here

React:

ReactJS is much easier to learn and use. ReactJS is a free and open-source front-end JavaScript library for building user interfaces based on UI components. to create interactive applications for mobile, web, and other platforms. To know more about relative links click here

Single sign-on(SSO):

Single sign-on (SSO) is a time-saving and highly secure user authentication process. SSO lets users access multiple applications with a single account and sign out instantly with one click.

How it Works:



how it works

Flow Diagram:



flow diagram

Steps:

Step 1: Create a LinkedIn client Id and client Secret

Check out this tutorial, to create a client Id and client secret.

Step 2: Set up a React project

Install Nodejs

Before we create React App we need to install node.js.

if you already installed node.js please ignore this step 2 and go to step 3

Step 3: Create a React-app

After installing Node.js open the terminal or command prompt and create the React app with the following commands

1npx create-react-app frontend

A sample screenshot of React app files is shown below.


index

Step 4: Configure the React project to establish a connection with LinkedIn.

After creating the React app then install the react-linkedin-login-oauth2 commands

1npm i react-linkedin-login-oauth2

In src/App.js, add the following code.

1import './App.css'; 2import linkedin from "./linkedin.png"; 3import {LinkedIn} from 'react-linkedin-login-oauth2'; 4 5 6function App() { 7 function handleFailure(e){ 8 alert(e) 9 } 10 function handleSuccess(e){ 11 fetch("http://127.0.0.1:8000/linkedin/",{ 12 method:"POST", 13 body:JSON.stringify({'auth_token':e}), 14 headers: { 15 'Content-Type': 'application/json; charset=utf-8' 16 } 17 }) 18 .then((res)=>res.json()) 19 .then((res)=>{ 20 document.getElementById("email_id").innerText=res['email'] 21 document.getElementById("Auth_token").innerText=res['tokens'] 22 }) 23 } 24 return ( 25 <div> 26 <LinkedIn 27 clientId="77dcf3sukwwhev" 28 redirectUri={`${window.location.origin}/linkedin`} 29 onSuccess={handleSuccess} 30 onFailure={handleFailure} 31 className='linkedin'> 32 {({ linkedInLogin }) => ( 33 <img 34 className='linkedin' 35 onClick={linkedInLogin} 36 src={linkedin} 37 alt="Sign in with Linked In" 38 39 /> 40 )} 41 </LinkedIn> 42 <div className='show_info'> 43 <div> 44 <label>Email Id: </label> 45 <label id='email_id'></label> 46 </div> 47 <div> 48 <label>Auth Token : </label> 49 <label id='Auth_token'></label> 50 </div> 51 </div> 52 </div> 53 ); 54} 55 56export default App;

The sample code for the App.js file can be found in the following GitHub URL.

You can run your app via CLI with the following command and view it in your browser:

1npm start

LINKEDIN

Step 5: Set up a Django project.

1: Install Python

Python3.6 or above is needed to create a Django project, therefore please install python and proceed to the next step.

2: Install Django:

Install the Django framework using the following command.

1pip install django

3: Create a Django Project:

Create a Django project using the below command.

1django-admin startproject backend

Step 6: Create a Django App:

After creating the Django project, then create the Django app

1python manage.py startapp accounts

A sample screenshot of Django project files is shown below.


accounts

Step 7: Configure the Django project to establish a connection with LinkedIn.

1: Install djangorestframework:

In this blog, we are using the Django Rest framework python library to create APIs, therefore the please install same to proceed further.

1pip install djangorestframework

2: Install django-cors-headers:

django-cors-headers library needs to establish a connection from the React frontend to Django API, hence please install the same using the below command.

1pip install django-cors-headers
  • In backend/settings.py, add the following piece of code:

1LINKEDIN_CLIENT_ID = "LinkedIn Client Id" 2LINKEDIN_CLIENT_SCERET = "Linked In Sceret" 3SOCIAL_SECRET = "Linked In Sceret" 4LINKEDIN_REDIRECT_URL = "http://localhost:3000/linkedin"
1CORS_ORIGIN_ALLOW_ALL = True
1MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware', 3 'django.contrib.sessions.middleware.SessionMiddleware', 4 'django.middleware.common.CommonMiddleware', 5 'django.middleware.csrf.CsrfViewMiddleware', 6 'django.contrib.auth.middleware.AuthenticationMiddleware', 7 'django.contrib.messages.middleware.MessageMiddleware', 8 'django.middleware.clickjacking.XFrameOptionsMiddleware', 9 'corsheaders.middleware.CorsMiddleware', # <<< newly added line 10]

Sample code for the /accounts/settings.py can be found in the following GitHub URL.

  • In your project, go to your /accounts directory and create a file called serializers.py.



serializer

In /accounts/serializers.py, add the following code.

1from django.conf import settings 2from rest_framework import serializers 3from library.sociallib import linkedin 4from library.register.register import register_social_user 5from rest_framework.exceptions import* 6 7 8class LinkedinSocialAuthSerializer(serializers.Serializer): 9 """Handles serialization of Linkedin related data""" 10 auth_token = serializers.CharField() 11 12 def validate_auth_token(self, auth_token): 13 user_data = linkedin.Linkedin.validate(auth_token) 14 try: 15 email = user_data['emailAddress'] 16 provider = 'linkedin' 17 except: 18 raise serializers.ValidationError( 19 'The token is invalid or expired. Please login again.' 20 ) 21 return register_social_user( 22 provider=provider, user_id=None, email=email, name=None)

Sample code for the /accounts/serializers.py can be found in the following GitHub URL.

  • Update the accounts/views.py file with the following code.

1from rest_framework.generics import GenericAPIView 2from .serializers import* 3from rest_framework.response import Response 4from rest_framework import status 5from rest_framework.permissions import AllowAny 6from rest_framework.decorators import permission_classes 7 8 9@permission_classes((AllowAny, )) 10class LinkedInSocialAuthView(GenericAPIView): 11 12 serializer_class = LinkedinSocialAuthSerializer 13 14 def post(self, request): 15 """ 16 POST with "auth_token" 17 Send an access token as from linkedin to get user information 18 """ 19 20 serializer = self.serializer_class(data=request.data) 21 serializer.is_valid(raise_exception=True) 22 data = ((serializer.validated_data)['auth_token']) 23 return Response(data, status=status.HTTP_200_OK)

Sample code for the /accounts/views.py can be found in the following Github URL.

 

  • Create the sociallib and register directory in the following hierarchy.

    library → socaillib

    library → register.

  • After that, please create a linkedin.py file inside the sociallib directory



LINKEDIN

In library/sociallib/linkedin.py, add the following snippet.

1from django.conf import settings 2import urllib.request as requests 3import json 4from urllib.parse import urlunparse 5 6 7class Linkedin: 8 """ 9 Github class to fetch the user info and return it 10 """ 11 @staticmethod 12 def validate(auth_token): 13 """ 14 validate method Queries the linkedin url to fetch the user info 15 """ 16 try: 17 access_token_url = "https://www.linkedin.com/oauth/v2/accessToken?grant_type=authorization_code&client_id=%s&client_secret=%s&code=%s&redirect_uri=%s" % ( 18 settings.LINKEDIN_CLIENT_ID, settings.LINKEDIN_CLIENT_SCERET, auth_token, settings.LINKEDIN_REDIRECT_URL) 19 req = requests.urlopen(access_token_url) 20 reply = req.read() 21 access_token_json_decode = reply.decode('utf-8') 22 access_token_json = json.loads(access_token_json_decode) 23 access_token = access_token_json['access_token'] 24 25 url = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))' 26 headers = { 27 "Authorization": f"Bearer {access_token}", 28 } 29 req = requests.Request(url, headers=headers) 30 response = requests.urlopen(req) 31 reply = response.read() 32 data_response = reply.decode('utf-8') 33 user_info = json.loads(data_response) 34 return user_info['elements'][0]['handle~'] 35 36 except: 37 return "The token is invalid or expired." 38

Sample code for the library/sociallib/linkedin.py file can be found in the following Github URL.

  • Navigate to the library/register directory and create a file called register.py



register

In library/register/register.py, add the following code.

1from rest_framework.authtoken.models import Token 2 3from accounts.models import User 4from django.conf import settings 5from rest_framework.exceptions import AuthenticationFailed 6 7 8def register_social_user(provider, user_id, email, name): 9 filtered_user_by_email = User.objects.filter(email=email) 10 11 if filtered_user_by_email.exists(): 12 if provider == filtered_user_by_email[0].auth_provider: 13 new_user = User.objects.get(email=email) 14 15 registered_user = User.objects.get(email=email) 16 registered_user.check_password(settings.SOCIAL_SECRET) 17 18 Token.objects.filter(user=registered_user).delete() 19 Token.objects.create(user=registered_user) 20 new_token = list(Token.objects.filter( 21 user_id=registered_user).values("key")) 22 23 return { 24 'username': registered_user.username, 25 'email': registered_user.email, 26 'tokens': str(new_token[0]['key'])} 27 28 else: 29 raise AuthenticationFailed( 30 detail='Please continue your login using ' + filtered_user_by_email[0].auth_provider) 31 32 else: 33 user = { 34 'username': email, 'email': email, 35 'password': settings.SOCIAL_SECRET 36 } 37 user = User.objects.create_user(**user) 38 user.is_active = True 39 user.auth_provider = provider 40 user.save() 41 new_user = User.objects.get(email=email) 42 new_user.check_password(settings.SOCIAL_SECRET) 43 Token.objects.create(user=new_user) 44 new_token = list(Token.objects.filter(user_id=new_user).values("key")) 45 return { 46 'email': new_user.email, 47 'username': new_user.username, 48 'tokens': str(new_token[0]['key']), 49 } 50 51 52

Sample code for the library/register/register.py file can be found in the following Github URL.

 

  • Add the accounts/urls.py file with the following content.

1from django.urls import path 2from .views import* 3 4urlpatterns = [ 5 path('linkedin/', LinkedInSocialAuthView.as_view()), 6]

An example screenshot of the Django project is shown below.


urls


Sample code for the accounts/urls.py file can be found in the following Github URL.

  • Finally, Run the Django application using the following command.

1 python manage.py runserver

 

A Sample Github repo, with all the required configurations, is given below.

Result:

After finishing all the steps mentioned above, please go to the web browser, and try to access the React application (i.e http://localhost:3000). An example output screenshot is given below.


result

 

Comments