![]() |
![]() |
|
|
|
|
|
Like my work? Check out HexaLex, my game for iPhone & iPod Touch. It's a crossword game like Scrabble, but played with hexagonal tiles. http://www.hexalex.com If you’re building an iPhone app that uses Facebook Connect you’re eventually going to need a session proxy. The session proxy acts as a middleman between your iPhone app and Facebook’s servers, so that you don’t have to distribute your Facebook app secret with your app, where it can easily be extracted by someone knowledgeable with a hex editor. Before I start, I should address the inevitable “what about OAuth2″ comments. Yes, OAuth2 is the new hotness for Facebook authentication, but the Facebook Connect iPhone SDK isn’t going to get broken (intentionally!) any time soon. (I have that on authority from a friend inside Facebook, BTW.) If you’ve got the time to replicate the functionality of FBConnect for the new world order I salute you, but otherwise this code may come in handy and will continue to function until a full-featured replacement for FBConnect arrives. With a session proxy (say at http://your-server.example.com/fbproxy), this is how the client establishes a session:
A_SIGNATURE is generated using your FB app secret, so Facebook knows the request is legit. Facebook returns a session key & secret that can be used to make Facebook API calls from the phone. If you’re wondering (like I did) how this is any more secure than shipping your app secret directly, you should understand that a session key is much less powerful than an app secret. The app secret is basically the root password for your app, while a session key gets you an unprivileged user account. With HexaLex I’ve used Google App Engine to host most of the backend service, so I ended up adapting some sample code I found online to do the job. (minifb is particularly readable.) I didn’t want to pull in a bunch of other dependencies, so this code is self-sufficient. I’m using Google’s webapp framework so that’s what’s used in the code, but it should be easy to adapt to whatever framework you favor. Without further ado, here’s the code: """ To use this, write in your Facebook API key and secret below and then add FacebookSessionProxy to your list of url handlers: application = webapp.WSGIApplication( [('/fbproxy', FacebookSessionProxy), ...]) Then in your iPhone code use something like session = [FBSession sessionForApplication:myApiKey getSessionProxy:@"http://yourApp.appspot.com/fbproxy" delegate:self]; """ import hashlib import httplib import urllib from google.appengine.ext import webapp # This lambda prevents the secret from appearing in cgitb backtraces FB_API_SECRET = lambda:"YOUR_API_SECRET" FB_API_KEY = "YOUR_API_KEY" FB_API_HOST="api.facebook.com" FB_API_PATH="/restserver.php" def facebook_signature(paramsDict): """Compute the signature of a Facebook request""" sorted = paramsDict.items() sorted.sort() trace = ''.join(["%s=%s" % x for x in sorted]) trace += FB_API_SECRET() md5 = hashlib.md5() md5.update(trace) return md5.hexdigest() def get_fb_session(auth_token): """Request a Facebook session using the given auth_token""" params={ "api_key":FB_API_KEY, "v":"1.0", "auth_token":auth_token, "generate_session_secret":"1", "method":"auth.getSession", } params["sig"] = facebook_signature(params) encoded_params = urllib.urlencode(params) headers = { "Content-type":"application/x-www-form-urlencoded", } conn = httplib.HTTPConnection(FB_API_HOST) conn.request("POST", FB_API_PATH, encoded_params, headers) return conn.getresponse() class FacebookSessionProxy(webapp.RequestHandler): def get(self): response = self.response auth_token = self.request.get('auth_token') if len(auth_token) == 0: response.set_status(httplib.BAD_REQUEST) response.out.write("Facebook login error: no auth_token given.") return fbResponse = get_fb_session(auth_token) response.out.write(fbResponse.read()) response.set_status(fbResponse.status, fbResponse.reason) response.headers['Content-Type'] = fbResponse.getheader('content-type') # The End Update: I fixed a bug in the call to get_fb_session. Thanks to Justin Williams for reporting it.
|
|
![]() |
![]() |



