From: Stas Kravets Date: Thu, 12 Jul 2012 09:07:08 +0000 (+0400) Subject: Facebook canvas application auth example X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=2171b04dabe6064cf4fda8003fd56ec880b9ec85;p=django-social-auth.git Facebook canvas application auth example --- diff --git a/README.rst b/README.rst index 5759950..0f9ec76 100644 --- a/README.rst +++ b/README.rst @@ -823,8 +823,15 @@ http://127.0.0.1:8000 or http://localhost:8000 because it won't work when testing. Instead I define http://myapp.com and setup a mapping on /etc/hosts or use dnsmasq_. -If you need to perform authentication from Facebook Canvas application, take a -look to `Facebook Canvas Application Authentication`_. +If you need to perform authentication from Facebook Canvas application: + - Create your canvas application at http://developers.facebook.com/apps + - In Facebook application settings specify your canvas URL ``mysite.com/fb`` (current default) + - Setup your Django Social Auth settings like you usually do for Facebook authentication (FACEBOOK_APP_ID etc) + - Launch manage.py via sudo ``./manage.py mysite.com:80`` for browser to be able to load it when Facebook calls canvas URL + - Open your Facebook page via http://apps.facebook.com/app_namespace or better via http://www.facebook.com/pages/user-name/user-id?sk=app_app-id + - After that you will see this page in a right way and will able to connect to application and login automatically after connection + +More info on the topic at `Facebook Canvas Application Authentication`_. Orkut ^^^^^ diff --git a/doc/backends/facebook.rst b/doc/backends/facebook.rst index b7df58d..c888df1 100644 --- a/doc/backends/facebook.rst +++ b/doc/backends/facebook.rst @@ -32,8 +32,15 @@ http://127.0.0.1:8000 or http://localhost:8000 because it won't work when testing. Instead I define http://myapp.com and setup a mapping on /etc/hosts or use dnsmasq_. -If you need to perform authentication from Facebook Canvas application, take a -look to `Facebook Canvas Application Authentication`_. +If you need to perform authentication from Facebook Canvas application: + - Create your canvas application at http://developers.facebook.com/apps + - In Facebook application settings specify your canvas URL ``mysite.com/fb`` (current default) + - Setup your Django Social Auth settings like you usually do for Facebook authentication (FACEBOOK_APP_ID etc) + - Launch manage.py via sudo ``./manage.py mysite.com:80`` for browser to be able to load it when Facebook calls canvas URL + - Open your Facebook page via http://apps.facebook.com/app_namespace or better via http://www.facebook.com/pages/user-name/user-id?sk=app_app-id + - After that you will see this page in a right way and will able to connect to application and login automatically after connection + +More info on the topic at `Facebook Canvas Application Authentication`_. .. _dnsmasq: http://www.thekelleys.org.uk/dnsmasq/doc.html .. _Facebook development resources: http://developers.facebook.com/docs/authentication/ diff --git a/example/app/facebook.py b/example/app/facebook.py new file mode 100644 index 0000000..eb2a71a --- /dev/null +++ b/example/app/facebook.py @@ -0,0 +1,78 @@ +from django.contrib.auth import BACKEND_SESSION_KEY +from django.contrib.auth.models import AnonymousUser +from django.http import HttpResponse +from django.shortcuts import render_to_response +from django.template.context import RequestContext + +from django.views.decorators.csrf import csrf_exempt +from django.core.cache import cache + +from social_auth.models import UserSocialAuth +from social_auth.views import complete as social_complete +from social_auth.utils import setting +from social_auth.backends.facebook import load_signed_request, FacebookBackend + +def is_complete_authentication(request): + return request.user.is_authenticated() and FacebookBackend.__name__ in request.session.get(BACKEND_SESSION_KEY, '') + +def get_access_token(user): + key = str(user.id) + access_token = cache.get(key) + + # If cache is empty read the database + if access_token is None: + try: + social_user = user.social_user if hasattr(user, 'social_user') \ + else UserSocialAuth.objects.get(user=user.id, provider=FacebookBackend.name) + except UserSocialAuth.DoesNotExist: + return None + + if social_user.extra_data: + access_token = social_user.extra_data.get('access_token') + expires = social_user.extra_data.get('expires') + + cache.set(key, access_token, int(expires) if expires is not None else 0) + + return access_token + +# Facebook decorator to setup environment +def facebook_decorator(func): + def wrapper(request, *args, **kwargs): + user = request.user + + # User must me logged via FB backend in order to ensure we talk about the same person + if not is_complete_authentication(request): + try: + user = social_complete(request, FacebookBackend.name) + except ValueError: + pass # no matter if failed + + # Not recommended way for FB, but still something we need to be aware of + if isinstance(user, HttpResponse): + kwargs.update({'auth_response': user}) + # Need to re-check the completion + else: + if is_complete_authentication(request): + kwargs.update({'access_token': get_access_token(request.user)}) + else: + request.user = AnonymousUser() + + signed_request = load_signed_request(request.REQUEST.get('signed_request', '')) + if signed_request: + kwargs.update({'signed_request': signed_request}) + + return func(request, *args, **kwargs) + + return wrapper + + +@csrf_exempt +@facebook_decorator +def facebook_view(request, *args, **kwargs): + # If there is a ready response just return it. Not recommended though. + auth_response = kwargs.get('auth_response') + if auth_response: + return auth_response + + return render_to_response('facebook.html', {'fb_app_id':setting('FACEBOOK_APP_ID'), + 'warning': request.method == 'GET'}, RequestContext(request)) \ No newline at end of file diff --git a/example/settings.py b/example/settings.py index 8983f2b..935ee23 100644 --- a/example/settings.py +++ b/example/settings.py @@ -24,6 +24,13 @@ DATABASES = { } } +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + 'LOCATION': 'unique-snowflake' + } +} + TIME_ZONE = 'America/Chicago' LANGUAGE_CODE = 'en-us' SITE_ID = 1 diff --git a/example/templates/facebook.html b/example/templates/facebook.html new file mode 100644 index 0000000..075a5b3 --- /dev/null +++ b/example/templates/facebook.html @@ -0,0 +1,60 @@ +{% extends "base.html" %} + +{% block script %} + +{% endblock %} + +{% block heading %}Facebook Canvas Application Authentication{% endblock %} +{% block content %} + {% if user.is_anonymous %} + {% if warning %} +

You are using GET request to this page, and this is not something Facebook usually does. + To make a real test you need to do following: +

+
    +
  1. Create your canvas application at Facebook.
  2. +
  3. In Facebook application settings specify your canvas URL mysite.com/fb (current default).
  4. +
  5. Setup your Django Social Auth settings like you usually do for Facebook authentication (FACEBOOK_APP_ID etc).
  6. +
  7. Launch manage.py via sudo ./manage.py mysite.com:80 for browser to be able to load it when Facebook calls canvas URL.
  8. +
  9. Open your Facebook page via apps.facebook.com/app_namespace or better via www.facebook.com/pages/user-name/user-id?sk=app_app-id
  10. +
  11. After that you will see this page in a right way and will able to connect to application and login automatically after connection.
  12. +
+ {% else %} +

You are a guest in this Facebook application.

+ Click to connect and authenticate + {% endif %} + {% else %} +

Authenticated successfully as {{ user }}

+ Done + {% endif %} + +
+ +{% endblock %} \ No newline at end of file diff --git a/example/templates/home.html b/example/templates/home.html index edf90f8..61ef7f4 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -91,6 +91,7 @@

Login using other authentication systems:

diff --git a/example/urls.py b/example/urls.py index c55e328..cb6c287 100644 --- a/example/urls.py +++ b/example/urls.py @@ -2,7 +2,7 @@ from django.conf.urls.defaults import patterns, url, include from django.contrib import admin from app.views import home, done, logout, error, form, form2 - +from app.facebook import facebook_view admin.autodiscover() @@ -14,5 +14,6 @@ urlpatterns = patterns('', url(r'^form/$', form, name='form'), url(r'^form2/$', form2, name='form2'), url(r'^admin/', include(admin.site.urls)), + url(r'^fb/', facebook_view, name='fb_app'), url(r'', include('social_auth.urls')), )