RkBlog

Hardware, programming and astronomy tutorials and reviews.

Simple Django applications for writing Facebook applications and authentication

A quick look through several pozytywnie.pl Django applications handling Facebook SDK and authentication

Creating Facebook applications or integrating websites with Facebook isn't complex or very time consuming. In case of Django there is for example django-facebook package that provides a lot of Facebook related features.

Pozytywnie.pl, a company I work with released a set of small applications that were used internally to make Facebook applications as well as Facebook authentication integrations. In this article I'll showcase those applications.

All applications are available on github. Most of recently released applications aren't yet on PyPi so you will have to install them from git. I've also created a showcase Django project in my django-examples repository. It has all the required configuration and showcases nearly every application (notifications app isn't there).

To run the example project install requirements and then start the development server. There is a SQLite database with example data which will be displayed on the main page (you can start with a clean DB and enter a post in the admin panel too). The main page will show posts, and on the post detail view there will be django-social-metadata example.

For checking other apps you will need a Facebook application (ID, secret from the app and canvas url set in the Facebook application). I'll cover showcased applications in a moment. The test view is under /canvas/ URL. Facebook requires SSL for applications and page tabs and the example projects has simple support for running via https. In Facebook application configuration set https://localhost:8000/canvas/ as the canvas URL and then run manage.py runsslserver which will run it on https://localhost:8000. Open the url in the browser - SSL certificate won't be trusted so add a rule to open it. Then you can open it via the facebook application canvas - signed request can be tested/showcased that way.

django-social-metadata

django-social-metadata is a mixin and a template that adds social meta tags to DetailViews. Those tags are used by Facebook and Google+ to display widgets of pasted URLs.

Usage is simple. Import the mixin, add it to your DetailView and then set attributes or override methods used by the mixin:

import social_metadata.views


class PostView(social_metadata.views.SocialDataMixin, generic.DetailView):
    model = models.Post

    def get_social_title(self):
        return self.object.title

    def get_social_images(self):
        yield self.object.cover_image.url

    def get_social_description(self):
        return truncatewords(striptags(self.object.text), 50)


post_view = PostView.as_view()

Note that it needs full URLs to images and to the view. If your MEDIA_URL is an url and not a path then that will do it for ImageFields. As for view the model get_absolute_url is called and you have to implement it that it returns a full url and not just reversed path (using domain from Site model or other way).

You will also have to add social_metadata/default_tags.html template to HEAD section of you page, for example (assuming there is an extrahead block):

{% block extrahead %}
    {% include "social_metadata/default_tags.html" %}
{% endblock %}

As a result you will get a set of tags, that will look like:

<meta property="og:title" content="Lorem ipsum dolor sit amet2"/> 
<meta itemprop="name" content="Lorem ipsum dolor sit amet2"> 

<meta property="og:description" content="Lorem ipsum dolor sit amet,..."/> 
<meta itemprop="description" content="Lorem ipsum dolor sit amet, Lorem..."> 

<meta property="og:image" content="http://localhost:8000/media/covers/eesp8266.jpg"/> 
<meta itemprop="image" content="http://localhost:8000/media/covers/eesp8266.jpg">  

<meta property="og:url" content="http://localhost:8000/post/2/"/>

After adding those tags you can debug them on Facebook using Facebook debugger, and also when you paste such url on your wall you should see that it's using data from those tags.

Facebook authenication applications

django-facebook-auth is the backend application for handling Facebook users. It has the FacebookUser model as well as authentication backends and token debugging celery tasks. It's used by other applications listed in this article.

facebook-javascript-sdk is a simple application that allows you to insert the Facebook JS SDK code with a template tag and also to hook up some JS code to it initialization.

facebook-javascript-authentication is an application for authenticating Facebook users in Django with the help of Facebook JavaScript SDK. The JS SDK authenticates against Facebook with given permissions scope and if successful passes the access token to the backend which then authenticates the user in Django.

This application set is a must have for Facebook applications as well as for sites that want Facebook login integration.

How to use it?

You will need a Facebook application, which can be created and managed on developers.facebook.com. When you create one copy it ID and secret to Django settings:

FACEBOOK_APP_SECRET = 'SECRET_HERE'
FACEBOOK_APP_ID = 'APP_ID_HERE'

Add to INSTALLED_APPS:

'facebook_auth',
'facebook_javascript_sdk',
'facebook_javascript_authentication',
'javascript_settings',

The javascript_settings application is used to pass the authentication view URL to JavaScript so that facebook_javascript_authentication can send an AJAX request to it.

We will also need authentication backends:

AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'facebook_auth.backends.FacebookBackend',
'facebook_auth.backends.FacebookJavascriptBackend',
)

Add to urls.py:

url(r'^facebook_javascript_authentication/', include('facebook_javascript_authentication.urls')),

In base template add javascript_settings code and facebook_javascript_authentication script:

<script type="text/javascript">{% javascript_settings %}</script>
<script type="text/javascript" src="{% static 'facebook_javascript_authentication/script.js' %}"></script>

And that's all what is needed. Now we can create integrate the Facebook login with our Django site. You can check my example, but in general it looks like so:

$(function() {
    $('.SOME_LOGIN_LINK').click(authenticateWithFacebook);
});

function authenticateWithFacebook() {
    loginDialog(successCallback);

    function successCallback(response) {
        if (response.status == 'ok') {
            alert('ok');
        } else {
            alert('error');
        }
    }
}

The loginDialog function will call Facebook authentication and if it's successful it will do an AJAX request to the backend. The backend will try to authenticate a user and it will return status of this operation (as well as some user data if successful). loginDialog will call the callback JS function with the backend response.

facebook_javascript_authentication has two functions that we can use. Example code used loginDialog(onSuccess, scope), but there is also login(access_token, onSuccess), which can be used if you already have the access token.

Facebook authentication and REST token authentication

Applications written in Ember.js, Angular and other JS frameworks will use a REST API and will have to use some authentication for API requests. Session can be used if everything is in the same app running in the same domain - but not always. Session authentication will set a cookie which may not always work. Facebook applications running in an Facebook iframe will have third-party-cookies problem, while projects where API is on different domain will have CORS cross domain requests. In such cases requests are often authenticated by tokens. Django Rest Framework has token authentication that can be used like that.

facebook_javascript_authentication will try to login the user - create the session and so on. For apps willing to use only tokens it would be better if that view would not do sessions and return the token. This can be done at the moment by subclassing the authentication view and overriding, extending some methods.

Start with subclassing facebook_javascript_authentication.views.AuthenticateFacebookUser. The _get_response_data method can be used to add token to the response data. The post method has the login function given as an argument (by default the Django login function). You can pass your own (like dummy empty function) to prevent user login (only authentication will be done).

The next step is something that should be changed/refactored soon in facebook_javascript_authentication, but even now you can make the JS code do AJAX request to your view and not to the original. You have to expose the view URL in javascript-settings:

def javascript_settings():
    return {
        'authenticate': reverse('my_auth_view')
    }

And then override facebook_javascript_authentication JS configuration in JavaScript:

configuration['facebook_javascript_authentication'] = configuration['my_application_with_auth_view'];

facebook-signed-request

facebook-signed-request handles special requests that Facebook makes to page tabs and Facebook applications (documentation) when a user opens them on Facebook. This application will verify this request and extract data from it. A middleware will assign extracted data to request.facebook. facebook-signed-request is a must-have for page tabs and Facebook applications.

Add facebook_signed_request to INSTALLED_APPS and then add some MIDDLEWARE_CLASSES:

'facebook_javascript_authentication.middlewares.P3PMiddleware',
'facebook_signed_request.middleware.SignedRequestMiddleware',

'facebook_signed_request.middleware.FacebookLoginMiddleware',

First two add somewhere after CommonMiddleware. The last one may be lower on the list. You will have to remove XFrameOptionsMiddleware or at least disable it for the exposed views.

To open a view within Facebook Canvas you will have to set it's url in the Facebook application configuration. Facebook accepts only HTTPS links so you will have to have a SSL certificate. In my example application I use https://localhost:8000/canvas/ as the canvas URL. Django development server can't do SSL but django-sslserver can. Just start your application with runsslserver.

facebook-notifications

facebook-notifications is used for sending notifications on Facebook (documentation). They can be used to notify about some changes, events happening in your Facebook application. To some extent notifications can be used for websites - you will have to make a view that will be hooked as the canvas url so that it can handle incoming clicks from the notifications (you can link only to your Facebook application in the notifications). Such view should either redirect or display given page within Facebook iframe.

django-facebook-datastore

django-facebook-datastore is an application that stores some info about the user. There are three models that store profile data, user friends (within application users only) and user likes. Some data is available only after you get reviewed by facebook (for given permissions).

To use this application you can write a task that will fetch data after for example user login. As a quick example I just used a post_save signal.

The End

I hope you got interested in those small but handy applications. They were used for quite some time in Pozytywnie.pl and they work, so they should be stable. Some work needs to be done to push them to pypi and to hook up test runners on Github repos. All comments, pull requests are welcomed. And also one more application may show up - for opengraph actions handling (one common workflow).

RkBlog

26 February 2015;

Comment article