I’m going to quickly walk you through how to build a server-side Facebook registration flow with Django. This is really basic and doesn’t rely on special libraries aside from httplib2 and urlib which are pretty standard.
First you need to create an app. I set my App Domain to localhost
and
Site URL to http://localhost:8000
for development purposes. You’ll probably
need to do the same if you’re using Django’s built in development server. Copy
over your App ID and App Secret into your settings.py
file:
FACEBOOK_APP_ID = 'YOUR_FACEBOOK_APP_ID'
FACEBOOK_SECRET_KEY = 'YOUR_FACEBOOK_APP_SECRET'
Now lets add a login button to your site, you can put this anywhere:
<a class="ui-button" href="https://www.facebook.com/dialog/oauth?
client_id=YOUR_FACEBOOK_APP_ID
&redirect_uri=http://localhost:8000/facebook/">Log In with Facebook</a>
Don’t forget to replace YOUR_FACEBOOK_APP_ID with your App ID. It’s okay if this is hardcoded. Just make sure you don’t accidentally expose your App Secret, this should not be used publicly.
You’ll notice we put http://localhost:8000/facebook/
as our redirect URI in
the button above. Now we need to create a view to handle this request because
Facebook will hand us a “code” at that location which is what we’ll need to
retrieve an access token for the user, thus completing the process. Add the
following to your urls.py
:
url(r'^facebook/$', 'views.facebook'),
Now add the following to your views.py
:
import httplib2
import urllib
from django.http import HttpResponseRedirect
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from django.utils import simplejson as json
from profiles.models import Profile
def facebook(request):
params = {
'client_id': settings.FACEBOOK_APP_ID,
'redirect_uri': 'http://localhost:8000/registration/facebook/',
'client_secret': settings.FACEBOOK_SECRET_KEY,
'code': request.GET['code']
}
http = httplib2.Http(timeout=15)
response, content = http.request('https://graph.facebook.com/oauth/access_token?%s' % urllib.urlencode(params))
# Find access token and expire (this is really gross)
params = content.split('&')
ACCESS_TOKEN = params[0].split('=')[1]
EXPIRE = params[1].split('=')[1]
# Get basic information about the person
response, content = http.request('https://graph.facebook.com/me?access_token=%s' % ACCESS_TOKEN)
data = json.loads(content)
# Try to find existing profile, create a new user if one doesn't exist
try:
profile = Profile.objects.get(facebook_uid=data['id'])
except Profile.DoesNotExist:
user = User.objects.create_user(data['username'], data['email'], data['id'])
profile = user.get_profile()
profile.facebook_uid = data['id']
# Update token and expire fields on profile
profile.facebook_access_token = ACCESS_TOKEN
profile.facebook_access_token_expires = EXPIRE
profile.save()
# Authenticate and log user in
user = authenticate(username=profile.user.username, password=profile.facebook_uid)
login(request, user)
return HttpResponseRedirect('/')
One thing you’ll immediately notice is I’m importing a Profile model. All you need to do here is create a profiles app that has a single model with a foreign key to a user and some fields to store our access token and when that token expires:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.ForeignKey(User, unique=True)
facebook_uid = models.PositiveIntegerField(blank=True, null=True)
facebook_access_token = models.CharField(blank=True, max_length=255)
facebook_access_token_expires = models.PositiveIntegerField(blank=True, null=True)
And then add the following to your settings.py so you can use the “get_profile()” convenience method on user objects:
AUTH_PROFILE_MODULE = 'profiles.profile'
There you have it. A really hacky Facebook registration flow for Django.
Some will probably notice I didn’t use the word OAuth anywhere in this post. Every time I see that term my eyes gloss over and my buzzword bullshit detector flips on. OAuth is a very simple concept that’s often over explained—hopefully people can run through this tutorial and grasp what’s happening by just looking at the code.