If you will have a look at OAuth examples on twitter apiwiki there are already examples available to use Sign in with Twitter with Django, so why this new howto and example code. Because being a perfectionist I like things to be the standard way, so for authentication django allows you to specify your own customized authentication backends. I thought why should not that be utilized to authenticate the Django User object with twitter.
There are few pre-requisites listed below in the order they are needed:
- simplejson
- oauth
- python-twitter
- oauth-python-twitter
- TwitterBackend from djangosnippets.org
This guide assumes that simplejson, oauth, python-twitter and oauth-python-twitter are already on your python path.
1. Now create a new Django project: twitterapp
$ django-admin startproject
2. Change to the project directory.
3. Now start a new app inside the project
$ python manage.py startapp twitterauth
4. Create a new directory: backends
$ mkdir backends
5. Change to the backends directory and create 2 new empty files.
$ cd backends
$ touch __init__.py
$ touch twitteroauth.py
6. Copy the code from TwitterBackend into the empty file: twitteroauth.py
7. Now configure your settings.py and add/edit following configuration variables
CONSUMER_KEY = "Your consumer key from twitter" CONSUMER_SECRET = "You consumer secret from twitter" AUTHENTICATION_BACKENDS = ( 'backends.twitteroauth.TwitterBackend', 'django.contrib.auth.backends.ModelBackend', ) AUTH_PROFILE_MODULE = "twitterauth.UserProfile" |
8. Now goto the twitterauth app directory and create a UserProfile module and post save signal processor as follows:
from django.db import models from django.db.models.signals import post_save from django.contrib.auth.models import User class UserProfile(models.Model): user = models.ForeignKey(User) access_token = models.CharField(max_length=255, blank=True, null=True, editable=False) profile_image_url = models.URLField(blank=True, null=True) location = models.CharField(max_length=100, blank=True, null=True) url = models.URLField(blank=True, null=True) description = models.CharField(max_length=160, blank=True, null=True) def __str__(self): return "%s's profile" % self.user def create_user_profile(sender, instance, created, **kwargs): if created: profile, created = UserProfile.objects.get_or_create(user=instance) post_save.connect(create_user_profile, sender=User) |
9. Now modify your views.py in twitterauth app directory as following:
from django.conf import settings from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth import login, authenticate from oauthtwitter import OAuthApi import oauth CONSUMER_KEY = getattr(settings, 'CONSUMER_KEY', 'YOUR_KEY') CONSUMER_SECRET = getattr(settings, 'CONSUMER_SECRET', 'YOUR_SECRET') def twitter_signin(request): twitter = OAuthApi(CONSUMER_KEY, CONSUMER_SECRET) request_token = twitter.getRequestToken() request.session['request_token'] = request_token.to_string() signin_url = twitter.getSigninURL(request_token) return HttpResponseRedirect(signin_url) def twitter_return(request): request_token = request.session.get('request_token', None) # If there is no request_token for session, # means we didn't redirect user to twitter if not request_token: # Redirect the user to the login page, # So the user can click on the sign-in with twitter button return HttpResponse("We didn't redirect you to twitter...") token = oauth.OAuthToken.from_string(request_token) # If the token from session and token from twitter does not match # means something bad happened to tokens if token.key != request.GET.get('oauth_token', 'no-token'): del request.session['request_token'] # Redirect the user to the login page return HttpResponse("Something wrong! Tokens do not match...") twitter = OAuthApi(CONSUMER_KEY, CONSUMER_SECRET, token) access_token = twitter.getAccessToken() request.session['access_token'] = access_token.to_string() auth_user = authenticate(access_token=access_token) # if user is authenticated then login user if auth_user: login(request, auth_user) else: # We were not able to authenticate user # Redirect to login page del request.session['access_token'] del request.session['request_token'] return HttpResponse("Unable to authenticate you!") # authentication was successful, use is now logged in return HttpResponse("You are logged in") |
10. Add the following 2 lines to urls.py at correct location.
url('^login/$', twitter_signin, name='login'), url('^return/$', twitter_return, name='return'), |
11. Now start the django devevelopment server
$ python manage.py runserver
12. Goto http://localhost:8000/login and you will be redirected to twitter for authentication, and if you have done everything correctly then after Allowing your application you will see the message that your are logged in.