In this article we will get to know about how to login to your django app by using social logins like Facebook and Google.

Start a simple Django project

$ django-admin.py startproject thirdauth
$ tree thirdauth/
thirdauth/
├── manage.py
└── thirdauth
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

Running ./manage.py syncdb and then ./manage.py runserver and navigating to localhost:8000 will show the familiar “It worked!” Django page. Let’s put some custom application code in place, so that we can tell whether the current user is authenticated or anonymous.

Show current user’s authentication status

Now, the very small customizations we’ll add are:

Add ‘thirdauth’ to INSTALLED_APPS

Create the template for the home page

Add a view for the home page

Add a URL pointing to the home page view

Relevant portion of settings.py:

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
...
'thirdauth',
)

Template: thirdauth/base.html:

<!DOCTYPE html>
<html lang="en">
 <head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>{% block title %}Third-party Authentication Tutorial{% endblock %}</title>

   <!-- Bootstrap -->
   <link href="/static/css/bootstrap.min.css" rel="stylesheet">
   <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
   <link href="/static/css/fbposter.css" rel="stylesheet">

   <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
   <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
   <!--[if lt IE 9]>
     <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
     <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
   <![endif]-->
 </head>
 <body>
   {% block main %}{% endblock %}
   <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
   <!-- Include all compiled plugins (below), or include individual files as needed -->
   <script src="/static/js/bootstrap.min.js"></script>
 </body>
</html>

Template: thirdauth/home.html:

{% extends 'thirdauth/base.html' %}

    {% block main %}
    <div>
    <h1>Third-party authentication demo</h1>

    <p>
    {% if user and not user.is_anonymous %}
     Hello {{ user.get_full_name|default:user.username }}!
    {% else %}
     I don’t think we’ve met before.
    {% endif %}
    </p>
    </div>
{% endblock %}

File views.py:

from django.shortcuts import render_to_response
from django.template.context import RequestContext

def home(request):
   context = RequestContext(request,
                           {'user': request.user})
   return render_to_response('thirdauth/home.html',
                             context_instance=context)

File urls.py:

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   url(r'^$', 'thirdauth.views.home', name='home'),
   url(r'^admin/', include(admin.site.urls)),
)

Install Python Social Auth

 pip install python-social-auth

Second, let’s make some modifications to our settings.py to include python-social-auth in our project:

INSTALLED_APPS = (
...
'social.apps.django_app.default',
...
)

    TEMPLATE_CONTEXT_PROCESSORS = (
   'django.contrib.auth.context_processors.auth',
   'django.core.context_processors.debug',
   'django.core.context_processors.i18n',
   'django.core.context_processors.media',
   'django.core.context_processors.static',
   'django.core.context_processors.tz',
   'django.contrib.messages.context_processors.messages',
   'social.apps.django_app.context_processors.backends',
   'social.apps.django_app.context_processors.login_redirect',
)

AUTHENTICATION_BACKENDS = (
   'social.backends.facebook.FacebookOAuth2',
   'social.backends.google.GoogleOAuth2',
   'social.backends.twitter.TwitterOAuth',
   'django.contrib.auth.backends.ModelBackend',
)

Lets update the urls module to include the new group of URLs:

urlpatterns = patterns('',
...
url('', include('social.apps.django_app.urls', namespace='social')),
...
)

And finally, let’s update the database models:

./manage.py syncdb

Add links for logging in and logging out.

Since we’ll be logging in and out multiple times, let’s include django.contrib.auth URLs into our URLs configuration:

urlpatterns = patterns('',
   ...
   url('', include('django.contrib.auth.urls', namespace='auth')),
   ...
)

Let’s modify our Home page template like this:

{% extends 'thirdauth/base.html' %}

{% block main %}
 <div>
 <h1>Third-party authentication demo</h1>

 <p>
   <ul>
   {% if user and not user.is_anonymous %}
     <li>
       <a>Hello {{ user.get_full_name|default:user.username }}!</a>
     </li>
     <li>
       <a href="{% url 'auth:logout' %}?next={{ request.path }}">Logout</a>
     </li>
   {% else %}
     <li>
       <a href="{% url 'social:begin' 'facebook' %}?next={{ request.path }}">Login with Facebook</a>
     </li>
     <li>
       <a href="{% url 'social:begin' 'google-oauth2' %}?next={{ request.path }}">Login with Google</a>
     </li>
     <li>
       <a href="{% url 'social:begin' 'twitter' %}?next={{ request.path }}">Login with Twitter</a>
     </li>
   {% endif %}
   </ul>
 </p>
 </div>
{% endblock %}

For the login and logout links in this template to work correctly, we need to modify a few things. First, let’s take care of logout, it’s easier. Just add ‘request’ to the context object that we pass into template-rendering code.

Updated views.py:

from django.shortcuts import render_to_response
from django.template.context import RequestContext

def home(request):
   context = RequestContext(request,
                           {'request': request,
                            'user': request.user})
   return render_to_response('thirdauth/home.html',
                             context_instance=context)

For login to work, let’s first add a LOGIN_REDIRECT_URL parameter to settings (to prevent the default /account/profile from raising a 404):

LOGIN_REDIRECT_URL = '/'

Get Client IDs for the social sites.

For All the social networks we are using in this demo, the process of obtaining an OAuth2 client ID (also known as application ID) is pretty similar. All of them will require that your application has a “real” URL – that is, not http://127.0.0.1 or http://localhost. You can add an entry in your /etc/hosts file that maps 127.0.0.1 to something like “test1.com”, and the URL of your application becomes http://test1.com:8000 – that is good enough for testing. You can change it in the social app settings when it goes into production.

Facebook:

Go to https://developers.facebook.com/apps/?action=create and click the green “Create New App” button.

In the settings of the newly-created application, click “Add Platform”. From the options provided, choose Web, and fill in the URL of the site (http://test1.com:8000 in our example).

Copy the App ID and App Secret, and place them into settings.py file:

SOCIAL_AUTH_FACEBOOK_KEY = …
SOCIAL_AUTH_FACEBOOK_SECRET = …

This should be enough to get your app to login with Facebook! Try logging in and out – you should get redirected between your app and FB OAuth2 service, and a new record in the User social auths table will get created, along with a new User record pointing to it.

Google:

Go to https://console.developers.google.com/ and create a new application.

Under APIs and Auth > Credentials, create a new Client ID.

Make sure to specify the right callback URL: http://test1.com:8000/complete/google-oauth2/

Copy the values into settings file:

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = …
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = …