]> git.parisson.com Git - django-social-auth.git/commitdiff
Facebook canvas application auth example
authorStas Kravets <krvss@mail.ru>
Thu, 12 Jul 2012 09:07:08 +0000 (13:07 +0400)
committerStas Kravets <krvss@mail.ru>
Thu, 12 Jul 2012 09:07:08 +0000 (13:07 +0400)
README.rst
doc/backends/facebook.rst
example/app/facebook.py [new file with mode: 0644]
example/settings.py
example/templates/facebook.html [new file with mode: 0644]
example/templates/home.html
example/urls.py

index 5759950bab51fe656a1d84657332bd2fa80c60d7..0f9ec767b13c78f2ebf7b9442c0e9d1657c2c1b6 100644 (file)
@@ -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
 ^^^^^
index b7df58d2b05865c14361376f7df6939cd9fdb2e8..c888df1b2a29265d5a74e2f35e23c3c6a5ad0e39 100644 (file)
@@ -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 (file)
index 0000000..eb2a71a
--- /dev/null
@@ -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
index 8983f2bdf62603801d7f36448d7b34aa84d7f8d8..935ee2377902b07345884063f30a7c05a421cbe4 100644 (file)
@@ -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 (file)
index 0000000..075a5b3
--- /dev/null
@@ -0,0 +1,60 @@
+{% extends "base.html" %}
+
+{% block script %}
+    <script type="text/javascript">
+    function startConnect(){
+        FB.login(function(response) {
+            if (response.authResponse) {
+                window.location = window.location +
+                        '?access_token=' + response.authResponse.accessToken +
+                        '&expires=' + response.authResponse.expiresIn +
+                        '&signed_request=' + response.authResponse.signedRequest;
+            }
+
+        }, {scope: "{{ app_scope }}" })
+    }
+    </script>
+{% endblock %}
+
+{% block heading %}Facebook Canvas Application Authentication{% endblock %}
+{% block content %}
+    {% if user.is_anonymous %}
+        {% if warning %}
+            <p>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:
+            </p>
+            <ol>
+                <li>Create your canvas application at <a href="https://developers.facebook.com/apps">Facebook</a>.</li>
+                <li>In Facebook application settings specify your canvas URL <b>mysite.com</b>/fb (current default). </li>
+                <li>Setup your Django Social Auth settings like you usually do for Facebook authentication (FACEBOOK_APP_ID etc).</li>
+                <li>Launch manage.py via sudo ./manage.py <b>mysite.com</b>:80 for browser to be able to load it when Facebook calls canvas URL.</li>
+                <li>Open your Facebook page via apps.facebook.com/<b>app_namespace</b> or better via www.facebook.com/pages/<b>user-name</b>/<b>user-id</b>?sk=app_<b>app-id</b></li>
+                <li>After that you will see this page in a right way and will able to connect to application and login automatically after connection.</li>
+            </ol>
+        {% else %}
+            <p>You are a guest in this Facebook application.</p>
+            <a href="#" onclick="startConnect(); return false;">Click to connect and authenticate</a>
+        {% endif %}
+    {% else %}
+            <p>Authenticated successfully as {{ user }}</p>
+            <a href="{% url done %}">Done</a>
+    {% endif %}
+
+    <div id="fb-root"></div>
+        <script type="text/javascript">
+        window.fbAsyncInit = function() {
+            FB.init({appId: {{ fb_app_id }}, status: true, cookie: true, xfbml: true, oauth: true});
+
+    window.setTimeout(function() {
+        FB.Canvas.setAutoResize();
+    }, 250);
+};
+
+    (function() {
+        var e = document.createElement('script'); e.async = true;
+        e.src = document.location.protocol +
+                '//connect.facebook.net/ru_RU/all.js';
+        document.getElementById('fb-root').appendChild(e);
+    }());
+    </script>
+{% endblock %}
\ No newline at end of file
index edf90f888ec7bc8c5b42ad463c83dd67b9a3fbf7..61ef7f47d139b3211afee30503a56881bbfcfabb 100644 (file)
@@ -91,6 +91,7 @@
 <div>
   <h3>Login using other authentication systems:</h3>
        <ul>
+        <li><a rel="nofollow" href="{% url fb_app %}">Facebook Canvas Application</a></li>
                <li><a rel="nofollow" href="{% url socialauth_begin "vkontakte" %}">VKontakte OpenAPI</a></li>
        </ul>
 </div>
index c55e3285bc9dd77df4c5445a813f14677cf2dde6..cb6c287a748c8f2ebacdebb1aea9dc97a91442f6 100644 (file)
@@ -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')),
 )