Created
April 5, 2011 21:36
-
-
Save ksamuel/904623 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# vim: ai ts=4 sts=4 et sw=4 | |
""" | |
Decorators to facilitate authentifications and redirections in Facebook | |
apps | |
""" | |
import uuid | |
import urllib2 | |
import json | |
import urlparse | |
from functools import update_wrapper | |
from urlparse import urljoin | |
from django.conf import settings | |
from django.shortcuts import redirect | |
from django.contrib.auth.models import User | |
from django.contrib.sites.models import Site | |
from django.http import HttpResponse | |
from utils import parse_signed_request, ParsingError | |
def require_auth(): | |
""" | |
Put it on a view. It will check if the 'signed_request' POST param is | |
available, and if not, will redirect to the facebook url for this app. | |
If 'signed_request' is available and the user is anonymous, log him | |
in using the Dynoo backend authentification system. | |
""" | |
def decorator(func): | |
def wrapper(request, *args, **kwargs): | |
app_settings = settings.FACEBOOK_APPS['dynoo'] | |
signed_request = request.POST.get('signed_request', None) | |
if getattr(settings, 'SKIP_AUTH', False): | |
uid = request.session['uuid'] = app_settings['test_uuid'] | |
device_id = request.session['device_id'] = app_settings['device_id'] | |
request.session['name'] = app_settings['test_name'] | |
else: | |
uid = request.session.get('uuid', None) | |
device_id = request.session.get('device_id', None) | |
# if the signed request is passed, check its content | |
# agains the one in session to ensure we are still | |
# dealing with the same user | |
if all((signed_request, uid, device_id)): | |
print "Checking against signed request" | |
print uid, device_id | |
# extract the FB user data from the signed request | |
# if there is any error, redirect to an error screen | |
try: | |
data = parse_signed_request(signed_request, | |
app_settings['secret_key']) | |
except ParsingError, e: | |
# todo: log on error | |
print "Parsing error" | |
return redirect('fb_dynoo:unknowned_error') | |
except Exception, e: | |
return redirect('fb_dynoo:unknowned_error') | |
try: | |
fuid = data['user_id'] | |
except KeyError, TypeError: | |
fuid = None | |
# if fuid does not match the one in session | |
# the user probably switched account | |
saved_fuid = request.session.get('fuid', None) | |
if not fuid or fuid != saved_fuid: | |
uid = None | |
device_id = None | |
print "Signed request doesn't match" | |
if not (uid and device_id): | |
print "Needs authentification" | |
request.session.clear() | |
device_id = device_id or str(uuid.uuid4()) | |
request.session['device_id'] = device_id | |
# calls the API once to check if this device_id is | |
# knowned. if yes, get the uid from it and log in | |
# the user | |
auth_url = app_settings['dynoo_auth_url'].rstrip() | |
app_url = app_settings['app_url'] | |
current_url = urllib2.quote(request.get_full_path()) | |
callback = "%s?redirect_path=%s" % (app_url, current_url) | |
url = '%s?device_id=%s&callback=%s' % ( | |
auth_url, device_id, urllib2.quote(callback)) | |
data = urllib2.urlopen(url).read(10000) | |
result = json.loads(data) | |
uid = result.get('uuid', None) | |
name = result.get('name', None) | |
fuid = result.get('fuid', None) | |
if not uid: | |
print "Unknowned user. Needs auth redirection" | |
print "Redirect to %s" % result['url'] | |
# return a response containing a javascript code | |
# that redirect the parent of the iframe to | |
# the permission page | |
# if we do a normal redirection, it will open | |
# facebook in the iframe and Facebook don't like | |
# recursion | |
redirect_page = """ | |
<head> | |
<script type="text/javascript"> | |
parent.location.href='%s'; | |
</script> | |
</head> | |
""" % result['url'] | |
return HttpResponse(redirect_page) | |
request.session['uuid'] = uid | |
request.session['name'] = name | |
request.session['fuid'] = fuid | |
return func(request, *args, **kwargs) | |
return update_wrapper(wrapper, func) | |
return decorator |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment