React/Single sign-on (SSO)/
Published on
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 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
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) 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.
Steps:
Check out this tutorial, to create a client Id and client secret.
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
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.
After creating the React app then install the react-login-github
commands
1npm i react-login-github
In src/App.js
, add the following code.
1import './App.css';
2import LoginGithub from 'react-login-github';
3import github from "./github.png"
4
5function App() {
6 function onSuccess(e) {
7 fetch("http://127.0.0.1:8000/github/", {
8 method: "POST",
9 body: JSON.stringify({ "auth_token": e.code }),
10 headers: {
11 'Content-Type': 'application/json; charset=utf-8'
12 }
13 })
14 .then((res) => res.json())
15 .then((response) => {
16 document.getElementById("email_id").innerText = response['email']
17 document.getElementById("auth_token").innerText = response['tokens']
18 })
19
20 }
21 function onFailure(e) {
22 alert(e)
23 }
24 return (
25 <div className="App">
26 <LoginGithub
27 clientId="Github client Id"
28 onSuccess={onSuccess}
29 onFailure={onFailure}
30
31 className="github">
32 <img src={github} alt="Sign in with github" className='github-image' ></img>
33 <h2 className='github-name'>Sign in with github</h2>
34
35 </LoginGithub>
36 <div className="show-user_info">
37 <div >
38 <label className="info">Email Id:</label>
39 <label id='email_id'></label>
40 </div>
41 <div >
42 <label className="info">Auth token:</label>
43 <label id="auth_token"></label>
44 </div>
45 </div>
46 </div>
47 );
48}
49
50export default App;
The sample code for the App.js
file can be found in the following GitHub URL.
github_sso_django_reactjs_example/App.js at master · episyche/github_sso_django_reactjs_example
You can run your app via CLI with the following command and view it in your browser:
1npm start
Python3.6 or above is needed to create a Django project, therefore please install python and proceed to the next step.
Install the Django framework using the following command.
1pip install django
Create a Django project using the below command.
1django-admin startproject backend
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.
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
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:
1GITHUB_CLIENT_ID = <CLIENT_ID>
2SOCIAL_SECRET = <SOCIAL_SECRET>
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]
11
Sample code for the /accounts/settings.py
can be found in the following GitHub URL.
github_sso_django_reactjs_example/settings.py at master · episyche/github_sso_django_reactjs_example
In your project, go to your /accounts
directory and create a file called serializers.py
.
In /accounts/serializers.py
, add the following code.
1from django.conf import settings
2from rest_framework import serializers
3from library.sociallib import github
4from library.register.register import register_social_user
5from rest_framework.exceptions import*
6
7class GithubSocialAuthSerializer(serializers.Serializer):
8 """Handles serialization of facebook related data"""
9 auth_token = serializers.CharField()
10
11 def validate_auth_token(self, auth_token):
12 user_data = github.Github.validate(auth_token)
13
14 try:
15 email = user_data['email']
16 provider = 'github'
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)
23
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 GithubSocialAuthView(GenericAPIView):
11
12 serializer_class = GithubSocialAuthSerializer
13
14 def post(self, request):
15 """
16 POST with "auth_token"
17 Send an access token as from github 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)
24
25
Sample code for the /accounts/views.py
can be found in the following Github URL.
github_sso_django_reactjs_example/views.py at master · episyche/github_sso_django_reactjs_example
Create the sociallib and register directory in the following hierarchy.
library → socaillib
library → register.
After that, please create a github.py
the file inside the sociallib directory
In library/sociallib/github.py
, add the following snippet.
1from django.conf import settings
2import urllib.request as requests
3import json
4
5class Github:
6 """
7 Github class to fetch the user info and return it
8 """
9 @staticmethod
10 def validate(auth_token):
11 """
12 validate method Queries the github url to fetch the user info
13 """
14 try:
15 url = 'https://github.com/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s' % (
16 settings.CLIENT_ID, settings.CLIENT_SCERET, auth_token)
17 req = requests.urlopen(url)
18 reply = req.read()
19 access_token = (reply.decode('utf-8').split('&'))[0][13:]
20 headers = {
21 "Authorization": f"token {access_token}",
22 "content-type": "application/json",
23 "Access-Control-Expose-Headers": "ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval"
24 }
25 user_info_url = "https://api.github.com/user/emails"
26 req = requests.Request(user_info_url, headers=headers)
27 response = requests.urlopen(req)
28 response = response.read()
29 data = response.decode('utf-8')
30 user_info = json.loads(data)
31 return user_info[0]
32 except:
33 return "The token is either invalid or has expired"
Sample code for the library/sociallib/github.py
file can be found in the following Github URL.
github_sso_django_reactjs_example/github.py at master · episyche/github_sso_django_reactjs_example
Navigate to the library/register
directory and create a file called register.py
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
Sample code for the library/register/register.py
file can be found in the following Github URL.
github_sso_django_reactjs_example/register.py at master · episyche/github_sso_django_reactjs_example
Add the accounts/urls.py
file with the following content.
1from django.urls import path
2from .views import*
3
4urlpatterns = [
5 path('github/', GithubSocialAuthView.as_view()),
6]
An example screenshot of the Django project is shown below.
Sample code for the accounts/urls.py
file can be found in the following Github URL.
github_sso_django_reactjs_example/urls.py at master · episyche/github_sso_django_reactjs_example
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.
GitHub - episyche/github_sso_django_reactjs_example
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.
Comments