Note that there are some explanatory texts on larger screens.

plurals
  1. POCurrent pure python solution for facebook-oauth?
    primarykey
    data
    text
    <p>It looks like I was not the only one trying to avoid javascript altogether for a solution with OAuth 2.0 serverside. People could do everything but they couldn't logout:</p> <p><a href="https://stackoverflow.com/questions/2764436/facebook-oauth-logout">Facebook Oauth Logout</a></p> <p><a href="https://stackoverflow.com/questions/2938466/oauth-logout-using-facebook-graph-api">Oauth Logout using facebook graph api</a></p> <p><a href="https://stackoverflow.com/questions/3385499/facebook-oauth2-logout-does-not-remove-fb-cookie">Facebook OAuth2 Logout does not remove fb_ cookie</a></p> <p>The <a href="http://developers.facebook.com/docs/authentication/" rel="nofollow noreferrer">official documentation</a> for OAuth 2.0 with Facebook says:</p> <blockquote> <p>You can log a user out of their Facebook session by directing them to the following URL:</p> <p><a href="https://www.facebook.com/logout.php?next=YOUR_URL&amp;access_token=ACCESS_TOKEN" rel="nofollow noreferrer">https://www.facebook.com/logout.php?next=YOUR_URL&amp;access_token=ACCESS_TOKEN</a></p> <p>YOUR_URL must be a URL in your site domain, as defined in the Developer App.</p> </blockquote> <p>I wanted to do everything serverside and I found that the suggested way to link leaves the cookie so that the logout link doesn't work: <code>https://www.facebook.com/logout.php?next=http://{{host}}&amp;access_token={{current_user.access_token}}</code> It does redirect but it doesn't log the user out of my website. It seemed like a Heisenbug since this was changing to me and there was not much documentation. I anyway seemed to be able to achieve the functionality with a handler that manipulates the cookie so that in effect the user is logged out:</p> <pre><code>class LogoutHandler(webapp2.RequestHandler): def get(self): current_user = main.get_user_from_cookie(self.request.cookies, facebookconf.FACEBOOK_APP_ID, facebookconf.FACEBOOK_APP_SECRET) if current_user: graph = main.GraphAPI(current_user["access_token"]) profile = graph.get_object("me") accessed_token = current_user["access_token"] self.set_cookie("fbsr_" + facebookconf.FACEBOOK_APP_ID, None, expires=time.time() - 86400) self.redirect("https://www.facebook.com/logout.php?next=http://%s&amp;access_token=%s" get_host(), accessed_token) def set_cookie(self, name, value, expires=None): if value is None: value = 'deleted' expires = datetime.timedelta(minutes=-50000) jar = Cookie.SimpleCookie() jar[name] = value jar[name]['path'] = '/' if expires: if isinstance(expires, datetime.timedelta): expires = datetime.datetime.now() + expires if isinstance(expires, datetime.datetime): expires = expires.strftime('%a, %d %b %Y %H:%M:%S') jar[name]['expires'] = expires self.response.headers.add_header(*jar.output().split(': ', 1)) def get_host(self): return os.environ.get('HTTP_HOST', os.environ['SERVER_NAME']) </code></pre> <p>So mapping the handler to /auth/logout and setting this to the link effectively logs the user out of my site (but I'm not sure about logging the user out of facebook, hopefully and untested)</p> <p>Some other parts of my code is handling the OAuth tokens and cookie lookups for the Oauth communication:</p> <pre><code>def get(self): fbuser=None profile = None access_token = None accessed_token = None logout = False if self.request.get('code'): args = dict( code = self.request.get('code'), client_id = facebookconf.FACEBOOK_APP_ID, client_secret = facebookconf.FACEBOOK_APP_SECRET, redirect_uri = 'self.get_host()/', ) file = urllib.urlopen("https://graph.facebook.com/oauth/access_token?" + urllib.urlencode(args)) try: token_response = file.read() finally: file.close() access_token = cgi.parse_qs(token_response)["access_token"][-1] graph = main.GraphAPI(access_token) user = graph.get_object("me") #write the access_token to the datastore fbuser = main.FBUser.get_by_key_name(user["id"]) logging.debug("fbuser "+fbuser.name) if not fbuser: fbuser = main.FBUser(key_name=str(user["id"]), id=str(user["id"]), name=user["name"], profile_url=user["link"], access_token=access_token) fbuser.put() elif fbuser.access_token != access_token: fbuser.access_token = access_token fbuser.put() current_user = main.get_user_from_cookie(self.request.cookies, facebookconf.FACEBOOK_APP_ID, facebookconf.FACEBOOK_APP_SECRET) if current_user: graph = main.GraphAPI(current_user["access_token"]) profile = graph.get_object("me") accessed_token = current_user["access_token"] </code></pre> <p>I didn't make a loginhandler since login basically is the code above at my root request handler. My user class is as follows:</p> <pre><code>class FBUser(db.Model): id = db.StringProperty(required=True) created = db.DateTimeProperty(auto_now_add=True) updated = db.DateTimeProperty(auto_now=True) name = db.StringProperty(required=True) profile_url = db.StringProperty() access_token = db.StringProperty(required=True) name = db.StringProperty(required=True) picture = db.StringProperty() email = db.StringProperty() </code></pre> <p>I mocked together two basic providers <img src="https://i.stack.imgur.com/uLx77.png" alt="enter image description here"> And I use the variable current_user for the facebook user and the variable user for the google user and the variable fbuser for a user who is logging in and therefore has no cookie match. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload