How to Set Up Django With Central OAuth2 Login
Tags: django
Published: 2019-10-24 20:52:48

I recently set up 10 Django servers to use the same Google G Suite corporate email login. This allows everyone in a company to log into all the Django and Discourse servers with the same email and password. This solution will also work with social logins from many providers such as Twitter, Facebook, GitHub. You can also use identity management solutions such as Auth0, Okta and OneLogin.

Although I assumed the task would be quick and easy, I ran into several challenges with outdated online examples.  I’ll explain what I did for deployment with Django 2.2, Python 3.7 and social-app-django 3.1.

Before standardizing on Google OAuth2, I deployed with Auth0.  Although the deployment was easy, users ran into problems with password resets using the Auth0 interface and there was no easy way to get support or ask questions to Auth0 during my assessment period.  I decided to drop Auth0 for the initial deployment and go with Google. 

The staff managing the content and users on all the Django and Discourse servers were already using Google email and therefore all staff had a Google account.

A GitHub repository of this example project is available 
[here](https://github.com/codetricity/django-social-login-example).

Begin this tutorial after you have your Django project and app started.

## Background

The screenshots and servers used in this example, are from the [RICOH THETA Developer Community](https://community.theta360.guide/) infrastructure run by [Oppkey Host](https://oppkey.host/). We initially started with local logins on Discourse servers and one-off web sites. As the number of servers grew, we ran into management problems.  We decided to standardize on Google OAuth2 due to simplicity of deployment.

A management interface allows content and user management staff from different companies to access the admin interface for many servers from different communities with the same email and password. Authorized servers are stored in a Profile object that extends the standard User object in Django.  In addition to Django servers, staff log into and manage Discourse servers using the same dashboard.

To keep this tutorial simple, the management interface is not shown in this tutorial.

## Setup

### Install Social Auth

    $ pip install social-auth-app-django

Or

    $ pipenv install social-auth-app-django

### console.developers.google.com

Go to https//console.developers.google.com and create new credentials.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/lqxcjit4j2u0mnr8c3xl.png)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/5n0cmrjvsibdfsxfcu1i.png)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/ygg06rabktwnozhm9rmx.png)

Select Web application.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/4vxt374nnnxow0igweu6.png)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/1zu8uddjlwfcyxnrbzjy.png)

Under Authorized redirect URIs, add the following:

    http://localhost:8000/complete/google-oauth2/
    https://project-domain.com/complete/google-oauth2/

Replace `project-domain.com` with the URL of your project server.

## Settings.py

```python
# social auth configuration

AUTHENTICATION_BACKENDS = (
    'social_core.backends.google.GoogleOAuth2',
    'django.contrib.auth.backends.ModelBackend',
)

LOGIN_URL = '/auth/login/google-oauth2/'

LOGIN_REDIRECT_URL = '/manage/'
LOGOUT_REDIRECT_URL = '/'
SOCIAL_AUTH_URL_NAMESPACE = 'social'


INSTALLED_APPS = [
    ...
    'social_django'
    ...
]
```

create a new file called `local_settings.py` and insert the following at the bottom of the `settings.py` file to create a connection from `settings.py` to `local_settings.py`:

```python
try:
    from .local_settings import *
except ImportError:
    pass
```

## local_settings.py

Put the values from Google into the constants below.

```python
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'GOOGLE_KEY'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'SECRET'
```

## urls.py

```
from django.contrib.auth.views import LogoutView
from django.urls import include

...

urlpatterns = [
path('admin/', admin.site.urls, name='administrator'),
path('', include('social_django.urls', namespace='social')),
path('', views_main.index, name='index'),
path(
    'logout/',
    LogoutView.as_view(template_name=settings.LOGOUT_REDIRECT_URL),
    name='logout'
    ),
path('manage/', views.manage, name='manage'),
]

views.py
def manage(request):
    return render(request, 'manage.html')

template manage.html
The snippet below uses Bootstrap for styling.
<div class="container pt-5">
        <h1>THETA Dream and Build Management Dashboard</h1>

        {% if user.is_authenticated %}

        <h2>
            <a href="/admin/">    Go To Dashboard</a>
        
        </h2>
        <hr>
        
        <a class="btn btn-primary mt-5" href="{% url 'logout' %}">Logout</a>
        
        {% else %}
        <a class="btn btn-primary" href="{% url 'social:begin' 'google-oauth2' %}">
                Login
                </a>
        {% endif %}
    </div>

```

make and migrate models

    $ python manage.py makemigrations 
    $ python manage.py migrate

run server and test

    $ python manage.py runserver

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/j78so4wc6iv1yz2bamvb.png)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2ni5siswdtzwfnss3ygz.png)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/m9ln71gvrs0p8dwyn5su.png)

## Summary

Although there are many ways to set up centralized login for different web applications, using Google OAuth2 is simple and well-documented.  If you’ve been hesitant to move off of local logins, it’s a great time to look at the available solutions.

Related Topics Not Covered in This Tutorial

* [Configuring Google login for Discourse](https://meta.discourse.org/t/configuring-google-login-for-discourse/15858)
* [Django Tutorial: Building and Securing Web Applications](https://auth0.com/blog/django-tutorial-building-and-securing-web-applications/)