How to connect Facebook OAuth 2.0 fully to the server?

Basically I want to keep this user's facebook id so that I can get more content through Facebook. Ideally, I want a solution that does not use javascript or cookie, just server-side, but there was no example, just directions, so I put together one that we can discuss. Here's the code that seems to work when I just associate the user with the OAuth dialog for my site:

https://www.facebook.com/dialog/oauth?client_id=164355773607006&redirect_uri=http://www.kewlbusiness.com/oauth

Then I process it to get user data:

 class OAuthHandler(webapp2.RequestHandler): def get(self): args = dict( code = self.request.get('code'), client_id = facebookconf.FACEBOOK_APP_ID, client_secret = facebookconf.FACEBOOK_APP_SECRET, redirect_uri = 'http://www.koolbusiness.com/oauth', ) 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 = facebook.GraphAPI(access_token) user = graph.get_object("me") self.response.out.write(user["id"]) self.response.out.write(user["name"]) 

That way I can “log in with Facebook” for my site without a lot of dirty javascript and cookies that we don’t need. I wanted to enable "log in with Facebook" for my site. It should work without cookies and without javascript, but the first thing they try to do is Javascript and cookies. So I made a solution that seems to work without cookie and without javascript, just OAuth 2.0: Can you say something about my "solution"? The practical use I'm looking for allows you to use the simple function that the FB user did on my website and recognized facebook accounts to enter a process that is becoming standardized.

I just thought that it should work without javascript SDK and without cookie, and it seems to be so. Can you tell me what are my advantages and disadvantages in this “solution”? I think this is much better than Javascript + Cookie, so why do they trick us into using javascript and cookie when the minimal example seems to be a 100% server?

thanks

The update seems to be correct and behaves correctly, and I can also use userdata with a datatore and render my FB name on the first page without javascript and without cookie, just python:

 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() friends = db.StringListProperty() dirty = db.BooleanProperty() class I18NPage(I18NHandler): def get(self): 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 = 'http://www.kewlbusiness.com/', ) logging.debug("client_id"+str(args)) file = urllib.urlopen("https://graph.facebook.com/oauth/access_token?" + urllib.urlencode(args)) try: logging.debug("reading file") token_response = file.read() logging.debug("read file"+str(token_response)) 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 "+str(fbuser)) 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() self.render_jinja( 'home_jinja',request=self.request,fbuser=user,... 

having the fbuser variable for the facebook user, and the user of the variable for the google user now assumes that I use facebook for my site without a glitchy useless javascript + cookie.

Now I could visualize and view my facebook name from my site, which is great that it finally works the way it should be javascript independent and does not need a cookie.

Why is the documentation recommended to use javascript + cookie when serveride OAuth 2.0 is the cleanest solution? Do you agree that this is the best solution, since it does not depend on the use of javascript or cookie?

Update A possible duplicate question, when I now saw that other guys could not exit the server code, they had to resort to the Javascript SDK, and the requirement may be that it should and should work without javascript, so I did some debugging and found that “clearing” the cookie, and I had to change the name of the cookie, and although it works, I would like to get your comment and / or check how you think my project solved this. Disabling a link like this should work, but it is not. If I log out twice, and why this is a strange error, since I could fix it, but I still don’t know that a second hit is required to exit the system:

https://www.facebook.com/logout.php?next=http://www.myappengineproject.com&access_token=AAACVewZBArF4BACUDwnDap5OrQQ5dx0jsHEKPJkIJJ8GdXlYdni5K50xKw6s8BSIDZCpKBtVWF9maHMoJeF9ZCRRYM1zgZD

It seems that I was not the only one who tried to avoid javascript at all for a solution with an OAuth 2.0 server. People could do everything, but could not log out:

Facebook Oauth Logout

The official OAuth 2.0 Facebook documentation says:

You can withdraw a user from your Facebook session by directing them to the following URL:

https://www.facebook.com/logout.php?next=YOUR_URL&access_token=ACCESS_TOKEN

YOUR_URL must be a URL in your site domain, as defined in the Developer Application.

I wanted to do everything serveride, and I found that the proposed method of communication leaves a cookie in such a way that the exit link does not work: https://www.facebook.com/logout.php?next=http://{{host}}&access_token={{current_user.access_token}} It redirects, but does not register the user on my site. It seemed that this was Heisenbug, because it changed me, and there was little documentation. In any case, I was able to implement the functionality with a handler that manipulates the cookie so that the user actually logs out:

 class LogoutHandler(webapp2.RequestHandler): def get(self): self.set_cookie("fbsr_" + facebookconf.FACEBOOK_APP_ID, None, expires=time.time() - 86400) self.redirect("/") 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)) 

Thus, matching the handler with / auth / logout and setting this to the link effectively takes the user out of my site (without registering the user from facebook, I hope and not verified)

Some other parts of my code process OAuth tokens and cookies for Oauth communication:

 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 = 'http://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"] 

I did not do loginhandler, since the login is basically the code above in my root request handler. My user class is as follows:

 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() 

I mocked two major providers enter image description here And I use the current_user variable for the facebook user and the variable user for the google user and the fbuser variable for the user who logs in and therefore does not have any cookie.

The cookie search code I use is the following and I think I understand it and that it does what I want:

 def get_user_from_cookie(cookies, app_id, app_secret): """Parses the cookie set by the official Facebook JavaScript SDK. cookies should be a dictionary-like object mapping cookie names to cookie values. If the user is logged in via Facebook, we return a dictionary with the keys "uid" and "access_token". The former is the user Facebook ID, and the latter can be used to make authenticated requests to the Graph API. If the user is not logged in, we return None. Download the official Facebook JavaScript SDK at http://github.com/facebook/connect-js/. Read more about Facebook authentication at http://developers.facebook.com/docs/authentication/. """ logging.debug('getting user by cookie') cookie = cookies.get("fbsr_" + app_id, "") if not cookie: logging.debug('no cookie found') return None logging.debug('cookie found') response = parse_signed_request(cookie, app_secret) if not response: logging.debug('returning none') return None args = dict( code = response['code'], client_id = app_id, client_secret = app_secret, redirect_uri = '', ) 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] logging.debug('returning cookie') return dict( uid = response["user_id"], access_token = access_token, ) 

I had to study cookies to solve this problem and I hope you can comment more. To display the welcome message, 3 variables are required, one for the google user, one for the facebook user login, and the fbuser variable for the case mentioned in the answer:

JavaScript / Cookies are used when you try to authenticate a new user. It does not exist in your database, and you do not have its access token.

So, I had to use 3 variables, maybe you can do this with only two variables?

  {% if user or current_user or fbuser %} <div id="user-ident"> <span>{% trans %}Welcome,{% endtrans %} <b>{{ current_user.name }}{% if not current_user and user %}{{ user.nickname() }}{% endif %}{% if not current_user and not user and fbuser %}{{ fbuser.name }}{% endif %}</span> </div> {% endif %} 
+8
python google-app-engine facebook facebook-oauth facebook-graph-api
source share
2 answers

JavaScript / Cookies are used when you try to authenticate a new user. It does not exist in your database and you do not have access to it.

When you have Token user access, you can access the Facebook API from any programming language, via HTTP, without cookies / javascript, if you want. There is a python client, for example: http://github.com/pythonforfacebook/facebook-sdk (was https://github.com/facebook/python-sdk )

+1
source share

Found this out. It also looks good, and it serves more than just fb. https://code.google.com/p/gae-simpleauth/

+1
source share

All Articles