Signup Or Sign-In Using Google To Django Application

Signup Or Sign-In Using Google To Django Application

Nowadays most of the users are having the Gmail account. Registration/Login will take the time fill the form and submit to create or login to our website. Adding the functionality to login/signup with google makes it very easy to login or to register to our website.

There are many*third party django packages* are available to add google signup or google login to our django application. But, third-party packages will also provides the additional functionality that is not required for us If you only need just google login and registration. In this article we going to add the login with google or register with google functionality without using the third-party django packages.

Login to Google developers account "https://console.developers.google.com/apis/dashboard" . After login, look for "select a Project" dropdown it's visible only if you do not have any projects created, otherwise dropdown automatically selects one of the available projects. If available choose the project or create new project. After choosing the project click on the link credentials there you can find the create credentials dropdown box which is having the options like API key, Oauth client Id, etc., click on "Oauth client Id". It will ask you for application type then choose "Web Application" because we are working with web application. After choosing it, It will ask you for "Application Name", "Authorized JavaScript origins", "Authorized redirect URIs". Enter you application name for , For "Authorized JavaScript origins" enter value of your domain name if you are in production otherwise enter "https://learnbatta.com" (default for django dev app) and for "Authorized redirect URIs" enter the callback url in my case it is "https://learnbatta.com/google-login/". Google will post the data to us when user accept/reject our application to use user's google data. After click on save button It will produce "client id" and "client secret" which will be used to tell the google that we are authorized to use google apis, save "client id" and "client secret" in a text file, because, we will use it.

Update the "client id" and "client secret" in "settings.py" file.

GP_CLIENT_ID = 'xxxxxxxxxxxxxxxxxxxx'
GP_CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxxx'

Lets talk about the authentication process with Gmail login

Our App <===> Gmail App <===> Gmail Servers

Lets start with very basic flow, when user clicks on the login with google button/link we redirect the user to gmail and asks for user's consent. After, google redirects the response to our application. Now we will implement it in our django application with the below code.

urls.py

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^google-login/$', views.google_login, name="google_login"),
]

views.py

from datetime import datetime
from urllib import urlencode
from django.conf import settings
from django.contrib import messages
from app.models import User

def google_login(request):
    redirect_uri = "%s://%s%s" % (
        request.scheme, request.get_host(), reverse('pain:google_login')
    )
    if('code' in request.GET):
        params = {
            'grant_type': 'authorization_code',
            'code': request.GET.get('code'),
            'redirect_uri': redirect_uri,
            'client_id': settings.GP_CLIENT_ID,
            'client_secret': settings.GP_CLIENT_SECRET
        }
        url = 'https://accounts.google.com/o/oauth2/token'
        response = requests.post(url, data=params)
        url = 'https://www.googleapis.com/oauth2/v1/userinfo'
        access_token = response.json().get('access_token')
        response = requests.get(url, params={'access_token': access_token})
        user_data = response.json()
        email = user_data.get('email')
        if email:
            user, _ = User.objects.get_or_create(email=email, username=email)
            gender = user_data.get('gender', '').lower()
            if gender == 'male':
                gender = 'M'
            elif gender == 'female':
                gender = 'F'
            else:
                gender = 'O'
            data = {
                'first_name': user_data.get('name', '').split()[0],
                'last_name': user_data.get('family_name'),
                'google_avatar': user_data.get('picture'),
                'gender': gender,
                'is_active': True
            }
            user.__dict__.update(data)
            user.save()
            user.backend = settings.AUTHENTICATION_BACKENDS[0]
            login(request, user)
        else:
            messages.error(
                request,
                'Unable to login with Gmail Please try again'
            )
        return redirect('/')
    else:
        url = "https://accounts.google.com/o/oauth2/auth?client_id=%s&response_type=code&scope=%s&redirect_uri=%s&state=google"
        scope = [
            "https://www.googleapis.com/auth/userinfo.profile",
            "https://www.googleapis.com/auth/userinfo.email"
        ]
        scope = " ".join(scope)
        url = url % (settings.GP_CLIENT_ID, scope, redirect_uri)
        return redirect(url)

when user clicks on the login with google button we redirect request to google/gmail with google client id, redirect uri for response, scope is to authorize to get the resource. After successful login google will return response to our redirect uri with access token code or authorization code. By using the authorization code we send the request to google to get the user resources from the google api's. In above code I have requested the resources "full name, family name, user profile picture and gender".
After getting the resource if user is not existed in our database then we create and get a new user otherwise we simply get the user from db. Now, we have user object so, we make the user login and redirect user to home page(in my case).

References:
https://developers.google.com/identity/protocols/OAuth2