Web.py Tutorial – Facebook Authentication

This is a rehash of the old tutorial after the update in the documentation.

Facebook is one of the most widely used authentication system, used especially to reduce the hassle of signing up for a new application. In this tutorial, I will be showing one way to integrating facebook authentication for your typical application.

This tutorial makes use of Facebook’s Graph API instead of the different SDKs. This method will work as long as your client is able to connect to the internet to access the APIs, be it Android, iOS or other platforms.

There are 2 phases to Facebook’s authentication system — creating a session to request an access token, and requesting for an access token. In the first part, a code is return, it is then used to request an access token. The token is used to access the information using Facebook’s Graph’s API.

For the first part, you will redirect the user to the following page: https://www.facebook.com/dialog/oauth using the client_id and redirect_uri.

### Initiate first stage of the process
if not i.get('code'):
   raise web.seeother('https://www.facebook.com/dialog/oauth?client_id='+client_id+'&redirect_uri='+uri)

In the second part, the access_token will be requested from https://graph.facebook.com/v2.3/oauth/access_token. The client_id and client_secret, together with the code will be used to generate the access_token. Because details of the application are required for this process, it is more to do it through the server. For that, we will make use of the python requests library.

r = requests.get(fb_graph+'oauth/access_token', params={
    'client_id':client_id,
    'client_secret':client_secret,
    'code':i.get('code'),
    'redirect_uri':uri
}).json()

To test if the authentication actually works, we redirect to a site to test the Facebook Graph API. This is where we get the basic profile information about the user and the profile picture.

r = requests.get(fb_graph+'me', params={'access_token':i.get('access_token')}).json()

return "<html><h3>%s (%s)</h3><img src='%s' /><br/><a href='%s'>View Profile</a></html>"%(r['name'], r['gender'], fb_graph+r['id']+'/picture', r['link'])

For the full web.py application, with the structure of the different pages, visit the gist below.


import web
import requests
client_id = '<client id>'
client_secret = '<client secret>'
fb_graph = 'https://graph.facebook.com/v2.3/&#39;
urls = [
'/', 'Index',
'/login', 'Login'
]
app = web.application(urls, globals())
class Index:
def GET(self):
i = web.input()
if not i.get('access_token'):
raise web.seeother('/login')
r = requests.get(fb_graph+'me', params={'access_token':i.get('access_token')}).json()
return "<html><h3>%s (%s)</h3><img src='%s' /><br/><a href='%s'>View Profile</a></html>"%(r['name'], r['gender'], fb_graph+r['id']+'/picture', r['link'])
class Login:
def GET(self):
i = web.input()
uri = web.ctx.realhome+web.ctx.fullpath
### TODO: CSRF prevention with state variable
if not i.get('code'):
raise web.seeother('https://www.facebook.com/dialog/oauth?client_id='+client_id+'&redirect_uri='+uri)
r = requests.get(fb_graph+'oauth/access_token', params={
'client_id':client_id,
'client_secret':client_secret,
'code':i.get('code'),
'redirect_uri':uri
})
obj = r.json()
print obj
if obj.get('error'):
err = obj['error']
if not err.get('code'):
return "<h1 style='color:#F00;'>%s</h1>%s"%(err, obj['error_description'])
else:
raise web.seeother('/login')
raise web.seeother('/?access_token='+obj['access_token'])
if __name__=='__main__':
app.run()

view raw

fb_auth.py

hosted with ❤ by GitHub

Leave a comment