开发者

Authenticate with Google App Engine from an Iphone Native Client

I want to create an Iphone game where users can log in with their facebook credentials and authenticate with my server running on Google App Engine. I have gotten Facebook connect working on both the iPhone and Google App Engine. However, it seems that Facebook connect for the iPhone only authenti开发者_运维知识库cates you with Facebook's server and allows you to access the Facebook Api from .

The reason I want to do this, is so that I can store extra user data associated with a user account on GAE, but also have them log in with their Facebook credentials.

Is it possible to authenticate the user using their Facebook credentials using an iPhone native client, but authenticate with my server? It seems like Farmville for the iPhone does something like this.

Any ideas how this is done?


This is possible via an intermediate Facebook API proxy on your GAE app.

Skimming through some code I have that does this, I call the classic API's auth.getSession with auth_token and generate_session_secret provided by the client, and of course format is XML.

http://developers.facebook.com/docs/reference/rest/auth.getSession/

Essentially what happens is that the client logs in, gets an authentication token, posts that to the intermediate proxy which then asks Facebook for a session using that token, returning that to the Connect client.


Here is a GAE proxy that you can call from your iphone app using Facebook connect.

Call it facebookProxy or whatever and add a URL handler on GAE.

Call it from within the iPhone app using:

session = [FBSession sessionForApplication:myApiKey getSessionProxy:@"http://yourApp.appspot.com/facebookProxy" delegate:self];

Here is the python code for the proxy. I use a seperate constants file to store the Facebook app keys, so you need to change that to use it.

import cgi
import hashlib
import httplib
import urllib
import logging
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import webapp
from google.appengine.api import users
import Constants

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 += Constants.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":Constants.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)
    logging.debug("%s" % encoded_params)
    return conn.getresponse()

class FacebookSessionProxy(webapp.RequestHandler):
    def get(self):
        response = self.response
        auth_token = self.request.get('auth_token')
        logging.debug("AUTH TOKEN: %s" % 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

application = webapp.WSGIApplication(
                                    [
                                      ('/facebookproxy', FacebookSessionProxy),
                                    ],
                                    debug=True)

def main():
  logging.getLogger().setLevel(logging.DEBUG)
  run_wsgi_app(application)

if __name__ == "__main__":
  main()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜