Facebook GraphAPIError: (#4) Application request limit reached - on first request - python

I'm building a new app which is still in development, i.e., I am the only user. The user is authenticated on the frontend, which then passes a Facebook access token to the backend. I want to validate this token on the backend to make sure that it's still valid, that it matches this application, and that the user matches. As described in how to verify facebook access token? (and the official Facebook docs), this can be done by calling graph.facebook.com/debug_token.
When I make this call from my local machine, it works fine. When I do it using the Graph API Explorer debug tool, it works fine. It used to work fine from my backend, too, but a few days ago it stopped working and now I get this error every time I make this call:
GraphAPIError: (#4) Application request limit reached
I could not possibly have exceeded any limits since the total number of API calls is tiny (this app is still in development mode, and I'm making a single call per login, not batching anything, not trying to read a feed, etc.). In fact, the very first request I make on a given day causes this error. Here's Facebook's graph of the total number of API calls I'm making:
There are a number of questions about the same error e.g. Facebook Application Request limit reached, however in all of these cases, it appears that users were actually exceeding some request limit, whereas in this case, that doesn't seem possible. The error seems misleading.
My backend is written in Python and hosted on Google App Engine.
Any ideas what may be causing this?

It turns out that this had absolutely nothing to do with quotas. It was a bug in the Python code. Here's what I was doing (using the Facebook Python SDK).
import facebook
app_access_token = facebook.get_app_access_token(
FACEBOOK_KEYS['consumer_key'], FACEBOOK_KEYS['consumer_secret'])
graph = facebook.GraphAPI(app_access_token)
token_info = graph.get_object("debug_token?input_token=%s" %
access_token)
I changed the last line to the following:
token_info = graph.get_object("debug_token", input_token=access_token)
Now it works. The error was completely misleading. I suppose Facebook was getting confused and not seeing the right token. I filed a bug report with Facebook in the hope that the error message, at least, can be improved.

Related

Python authlib flask - how to handle refresh token?

I only need oauth2 for login so far, but I feel that to be reasonably complete, my app should still handle refresh tokens.
I'm fairly new to oauth, so here is my understanding:
By keeping access token lifetime short, but refresh token lifetime long, you force the client to "check in" regularly to renew the access token, and thereby maintain more control.
But how to actually do that using authlib and the flask integration?
There seems to be no refresh_token() on the FlaskRemoteApp, and I have not been able to find any example code showing this.
This seems to work to get a new token
res = oauth.myOauth2.fetch_access_token(refresh_token=session['tok_res']['refresh_token'])
session['tok_res'].update(res)
But fails when subsequently using the new access_token for an api call.
Could be a server error I suppose, or maybe I need to wait for the old token to expire before using the new one? The expires_at time, keeps updating and that makes no sense to me in that case.
It would be great if somebody could explain how refresh_token is intended to be used with authlib and flask.
Well, unless #lepture drops by with the answer, I have at least an answer.
I was simply missing grant_type='refresh_token' from my call.
So this now works as expected for me.
if session['oatoken']['expires_at'] - 2 < now: # refresh 2 seconds early
oatoken = oauth.myOauth2.fetch_access_token(
refresh_token=session['oatoken']['refresh_token'],
grant_type='refresh_token')
session['oatoken'].update(oatoken)
I played around a little with setting the update_token function in the registry, but was not able to make it work. In any case I believe this is only triggered if an api call using the token receives an "expired token" reply. In my case I'm only using Oauth for login, so I can just watch the expires_at time, and only hit the auth server when necessary.

How to change authentication type on Twitter API

We're building a simple script using the Tweepy Python library. We need to get some simple information on all of the accounts following our Twitter account.
Using the cursor Tweepy's built in this is quite easy, but we very rapidly hit the 15 request limit for the window. I've read that per-App (as opposed to per-user) authentication allows for 300 requests per minute, but I can't find anything in the Tweepy API that supports this.
Any pointers?
You should be able to use tweepy.AppAuthHandler in the same way that you're using OauthHandler.
auth = tweepy.AppAuthHandler(token, secret)
api = tweepy.API(auth)
For some reason, this isn't documented, but you can take a look at the code yourself on GitHub.
It also depends what kinds of requests you're making. There are no resources with a 15 request user limit that have a 300 request app limit. You can consult this chart to determine the limits for user and app auth for each endpoint. In any case, using them in conjunction will at least double your requests.
I'm not what information of your followers you are after exactly, but it might be part of the request followers/list. If so, you can set the field count to 200 which is the maximum value, while the default is only 20. That will save you some requests.

Is it possible to build a desktop based application using Twython without using Django? Oauth2 causing problem

I downloaded the Twython source code and compiled it on my system. I am developing a desktop app, rather than a web-app. Thus, I don't see the use of Django-Oauth2 implementation in my little project.
This is being asked in twython.py
self.request_token_url = 'http://twitter.com/oauth/request_token'
self.access_token_url = 'http://twitter.com/oauth/access_token'
self.authorize_url = 'http://twitter.com/oauth/authorize'
self.authenticate_url = 'http://twitter.com/oauth/authenticate'
self.twitter_token = twitter_token
self.twitter_secret = twitter_secret
self.oauth_token = oauth_token
self.oauth_secret = oauth_token_secret
self.callback_url = callback_url
The problem here is that,
I don't know what is a "twitter_secret" or a "twitter_token". In the twitter dev, after registering my app, I got my customer key and secret. Also, got twitter key and secret. My callback_url is None. And, as twitter forced me to mention a website, I gave my localhost address and it got accepted. Now, I don't know how to move forward with the Oauth2 authentication.
What should I do next?
I'm the author of Twython.
Sadly, OAuth is a less than ideal method for authenticating in... well, anything outside of a web browser. While it's possible you could figure out some hacky method to make this work, if you're concerned about the user experience you may just want to request xAuth permission from Twitter:
https://dev.twitter.com/docs/auth
It's still OAuth, so most of the internal Twython pieces should be fine. While Twython doesn't outright support xAuth (due to Twitter's stance on advocating not using it...), I'm definitely open to taking a patch or two if enough people need it. ;)
Another option would be OOB authentication (which requires your users getting and entering a PIN, not generally great UX).

Testing Django Facebook App

I'm making a Django app with Fandjango and I'm trying to unit test it with Django's test framework. The only thing is, in order to test effectively I need a "signed_request" parameter that Facebook sends with every request. Right now I'm logging the requests my server gets from Facebook and copying + pasting the signed_request token I get, but that only works for a few hours at a time.
Is there a simple way to handle this without doing a mock of the whole Facebook API?
Thanks!
You can use Test Users:
http://developers.facebook.com/docs/test_users/
I think the access token never expires, or at less until you delete the Test User.
Well, I understand it's also possible to authenticate fully server side, using just OAuth without Javascript SDK. In that case you should be able to aquire a valid token yourself. There are, I think some libraries that can be used for that like:
http://pypi.python.org/pypi/django-social-auth/
However please note, I've never done this myself so it's more of a suggestion, than a definite answer.
EDIT
It seems like social-auth has some testing functionality that is capable of automatically signing in to a facebook account. You could probably copy the code from there.

Google OAuth2 callbacks calls me without parameters

I have been running a service for some months now using Google's
OAuth2 authentication. Most of the time everything works well, but
there are occasional issues with callbacks coming back empty from Google to me: Something along the lines of 1 out of 15 callbacks arrives at my service completely without parameters in the GET request. Just a naked /my-callback-url request, no parameters at all.
I'm having quite some difficulty explaining this behaviour and neither can I find many references to it when searching the net.
I'm also so far unable to re-create this phenomenon in my own development environment, so my solution ideas have had to be mostly speculation: My first hunch at a quick-n-dirty work around was to re-generate the OAuth request URL and return a 302 redirect response back so Google can have another go. But that sounds like taking the risk of creating an infinite redirect loop if it would turn out that the problem originates from my code. I would very much prefer to understand what's actually going on.
Do any of you have experience of 'empty' OAuth2 callbacks from Google?
And in that case, what would be the most sensible way of handling
them? Or are there a typical error when generating the authentication
URL's that causes this behaviour (I'm using Python &
Requests-OAuthlib)
to handle my OAuth2 interaction).
I suspect that these requests are not redirects back from Google. There are crawlers and other hackers trying to hit every endpoint that they find on the web. So these could be just abusive requests.
If you can correlate the request with an empty parameter with a request that redirected from your server (based on IP address or a cookie you set before redirecting to Google) then we can try to investigate further.

Categories