google-app-enginesessionauthenticationtipfy

facebook auth problem with tipfy 1.0b


I'm trying to mimic the login page from the example http://tipfy-auth.appspot.com (source http://code.google.com/p/tipfy/source/browse/examples/auth/app/) without success. I seem to run in to problem when the user is redirected back to the page. The current request flow looks like:

LoginPage (LoginHandler) -> Facebook redirect (FacebookAuthHandler) 302 -> Facebook.com -> Facebook redirect (FacebookAuthHandler) 302 -> SignupPage (SignupHandler) 302 -> LoginPage(LoginHandler).

The problem here (as far as I figured) is the last 302(http-redirect) from signup (should be endpoint) to the loginpage again.

After some intense logging (can't find away to test this locally) it seems that a session is set when returning from facebook. The session is stored as a dict on the request handler (FacebookAuthHandler) in two places self.auth.session(a dict) and self.session(a SecureCookieSession) but after the redirect to SignupPage the self.auth.session is None.

The redirect from SignUpPage to LoginPage occurs due to that the SignupHandler's get method has a decorator @login_required that looks at self.auth.session to determine if the reuquest should be handled here or be redirected.

So why aren't the self.auth.session preserved between requests while the self.session are? Are self.auth.session set at every request? How are the sessions stored? If it's in the db, does the datastore type matter (master/slave or high replication).

I'm digging around the source code but can't find any thing helpful.

..fredrik

EDIT

Posted answer below.


Solution

  • I've narrowed it down to that the problem lies within session property of the SessionAuthStore class.

    When accessing the session property (this is the property @login_required looks at to determine if redirect the user or not) it runs this code (in tipfy.auth.SessionAuthStore):

    if not self.loaded:
        self._load_session_and_user()
    
    return self._session
    

    The problem here is that in the _load_session_and_user method expects to be able to a load a user from the datastore based on the 'token' key inside the session.

    Unfortunately there's no user when returning from Facebook. So it will fail and redirect the user to the login page.

    To proceed in my project i changed the code a bit, the @login_required (tipfy.auth.init.py)

    if not auth.session:
            auth._load_session() # If no session try to load it from the _session_base
    
        if not auth.session:
            return handler.redirect(auth.login_url())
    

    And a new method on MultiAuthStore class.

    def _load_session(self):
            self.loaded = True
            session = self._session_base.get('_auth', {})
            if session:
                self._session = session
    

    Probably not the best solution but it works.