Sunday, November 8, 2009

Enriching our RunAroundUser model with utility methods

Very much like PHP runaround application I have added some static and some instance methods which provider useful information such as:
  • Get the logged in user (either native user or the one which has used Facebook)
  • Get the name and email of user  (from facebook or the one stored in DataStore) 
  • Register the Facebook user in our datastore
  • Register the user to Facebook (Still in construction ......)
  • Methods to login and logout the user

Reading and Writing Cookies

Since runaround application uses Cookies to store the username, in this post we will see how to read and write using webapp framework.

Reading cookies is quite simple:

if request.cookies.has_key(USER_COOKIE_NAME):
            username = request.cookies[USER_COOKIE_NAME]
        

Writing cookies:

I have created a small function that should help:

def writeCookie(response,username):
    cookie = Cookie.SimpleCookie()
    cookie[USER_COOKIE_NAME] = username
    cookie[USER_COOKIE_NAME]["Path"] = "/"
    
    h = re.compile('^Set-Cookie:').sub('',cookie.output(),count=1)
         
    response.headers.add_header('Set-Cookie',str(h))

Facebook APIs and Using PyFacebook

Facebook platform expose access to its data using RESTful interfaces. Your application can request profile, friend, Page, group, photo, and event data using these interfaces.

Here you would find all the Facebook APIs and their documentation along with some examples.

To get data from Facebook platform you are essentially making HTTP requests (GET or POST) with XML or JSON formatted data in requests and response. The APIs in the above mentioned link give enough information about the format of these messages.

PyFacebook is a pythonic library that takes care of making these HTTP requests and expose a nice object oriented interfaces for your application to use. One downside of PyFacebook is lack of documentation and even when you will look at the source code you may not get a good idea of how to use it (at least it was the case for me). The reason behind it is how this library has been written and demonstrates the power of dynamic languages and meta programming. It is really wonderful.

Here is an example of how from your application you would like to get the name of the user for whom you have his facebook uid.

pyfacebookObj.users.getInfo([fb_uid], ['name'])[0]


Here pyfacebookObj is an object of Facebook class exposed by PyFacebook. If you look inside the PyFacebook code you would not find a field "users" so from where this field is coming and as the above code snippet shows this field is essentially an object of class which has "getInfo" method.

So what PyFacebook is doing is that it is creating a class for each of the Facebook exposed data service with corresponding methods at runtime. These are called Proxy classes which are generating by an API specification. The interesting thing is that PyFacebook did not need to write lot of classes (and methods).

Magical.

Rendering Cross Domain Receiver page

class XdReceiverPage(webapp.RequestHandler):
    def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'templates/xd_receiver.html')
        self.response.out.write(template.render(path, template_values))

In the base.html template now we need to tell Facebook JavaScript where to find our cross domain receiver file.


     

This shows that you can place xd_receiver.html anywhere as long as you can tell Facebook JavaScript where to find it.

and here is how the xd_receiver.html file looks like:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script>
</body>
</html>


Facebook documentation also describes details of xd_receiver here

Integrating Facebook Connect

After looking at the user and authentication management in the PHP code I figured that both of them so intertwined that it would be difficult to develop them separately so I am going to start integrating Facebook Connect for user authentication.

Facebook wiki also gives the description of a login session here

Facebook Connect is a technology used to delegate the authentication of users to Facebook platform. In a way it competes with technologies like openID, SAML and CardSpace.

What I really liked in Facebook Connect is their use of cross-domain communication channel  which enable it to ask the user for the credentials at the service provider (runaround in our case) website instead of redirecting to Facebook. I would also like to mention that the protocols that Facebook Connect use is proprietary unlike SAML and OpenID which are open protocols.

The library that I will using will be pyfacebook to communicate with Facebook platform.


First you need to sign up with Facebook developer which is described in great detail here.


It would be a good idea to also read Anatomy of a Facebook Connect Site but anyway in later posts I am going to explain the steps need to be taken in our Google App Engine webapp framework based runaround application.

Sunday, November 1, 2009

Authentication & Session Management in Runaround application

As per the design of Runaround application :
  • User can login using his/her facebook account or native account at runaround
  • For Facebook Connect authentication the session is managemed by Facebook and runaround make use of Facebook client APIs to get a handle on session
  • For native account authentication (in the sample app) there is no server session, only a cookie based session is used.

We all know that Cookie based session is not secure and the demo app duly mentions it here

Since we are in learning mode and trying to port the PHP application to Google App Engine it may be simple to have similar functionality (even though it is not secure). But later we must do the right thing to have server based sessions.

Session management in Google App Engine

It would have been really nice if session management was part of Google SDK. Here are some open source alternatives available:
  1. Google App Engine Utilities
  2. gmemsess
  3. Beaker with patch for App Engine 
  4. Session handling with MemCache