Problem with Facebook OAuth on Google Appengine - python

I am using the "Server Side" flow to get a user's permissions to access some information using Python on Google Appengine.
I am able to get the server generated code from Facebook after the user clicks on the "Allow" button.
However when I get the access token, I run into the following error:
Traceback (most recent call last):
File
"/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/init.py",
line 515, in call
handler.get(*groups) File "/base/data/home/apps/finisherph/1.348502373491720746/controllers.py",
line 21, in get
data = urllib2.urlopen(access_token_url)
File
"/base/python_runtime/python_dist/lib/python2.5/urllib2.py",
line 124, in urlopen
return _opener.open(url, data) File
"/base/python_runtime/python_dist/lib/python2.5/urllib2.py",
line 387, in open
response = meth(req, response) File
"/base/python_runtime/python_dist/lib/python2.5/urllib2.py",
line 498, in http_response
'http', request, response, code, msg, hdrs) File
"/base/python_runtime/python_dist/lib/python2.5/urllib2.py",
line 425, in error
return self._call_chain(*args) File
"/base/python_runtime/python_dist/lib/python2.5/urllib2.py",
line 360, in _call_chain
result = func(*args) File "/base/python_runtime/python_dist/lib/python2.5/urllib2.py",
line 506, in http_error_default
raise HTTPError(req.get_full_url(), code,
msg, hdrs, fp) HTTPError: HTTP Error
400: Bad Request
Here's the code in my controller where the response from facebook goes after user clicks on the "Allow" button. It's still a hack so the code is a little bit dirty. Still trying to make it work.
class Register(webapp.RequestHandler):
def get(self):
code=self.request.get('code')
logging.debug("code: "+code)
accesst_url=["https://graph.facebook.com/oauth/access_token?"]
accesst_url.append("client_id=CLIENT_ID&")
import urllib
accesst_url.append(urllib.urlencode
({'redirect_uri':'http://my.website.com/register/facebook/'}))
accesst_url.append('&')
accesst_url.append("client_secret=CLIENT_SECRET&")
accesst_url.append("".join(["code=",str(code)]))
logging.debug(accesst_url)
access_token_url="".join(accesst_url)
logging.debug(access_token_url)
import urllib2
data = urllib2.urlopen(access_token_url)
...
...
The error occurs here:
data = urllib2.urlopen(access_token_url)
when I copy and paste the access_token_url from my logs, I get the following error:
{ "error": {
"type": "OAuthException",
"message": "Error validating verification code." } }
What am I missing here?

It looks like you are trying to access the access_token as url, which is not quite right.
Here is an example which illustrates how OAuth authentication via FB is done over GAE.
You go to the https://graph.facebook.com/oauth/authorize? with your client_id and redirect_uri
Upon authorization, it gives a code and you use code and client_secret to get an access_token from https://graph.facebook.com/oauth/access_token
And then you use that access_token to operate as the Facebook user.

Related

GMail Oauth2 authentication for yagmail stops working after a few days

I've started using yagmail a while ago for sending mails via GMail using OAuth2.
The code that I use is straightforward:
def send_with_yagmail(self):
yag = yagmail.SMTP(self.our_email, oauth2_file="/<path_to>/credentials.json")
yag.send(self.to_email, self.message_subject, contents=self.message_body)
All was well for a few days, and then suddenly Gmail stopped sending mails with the following as part of the stack trace:
...
return get_oauth_string(user, oauth2_info)
File "/usr/local/lib/p│ython3.9/site-packages/yagmail/oauth2.py", line 96, in get_oauth_string
access_token, expires_in = refresh_authorization(**oauth2_info)
File "/usr/local/lib/python3.9/site-packages/yagmail/oauth2.py", line 91, in refresh_authorization
response = call_refresh_token(google_client_id, google_client_secret, google_refresh_token)
File "/usr/local/lib/python3.9/site-packages/yagmail/oauth2.py", line 71, in call_refresh_token
response = urlopen(request_url, encoded_params).read().decode('UTF-8')
File "/usr/local/lib/python3.9/urllib/request.py", line 214, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/lib/python3.9/urllib/request.py", line 523, in open
response = meth(req, response)
File "/usr/local/lib/python3.9/urllib/request.py", line 632, in http_response
response = self.parent.error(
File "/usr/local/lib/python3.9/urllib/request.py", line 561, in error
return self._call_chain(*args)
File "/usr/local/lib/python3.9/urllib/request.py", line 494, in _call_chain
result = func(*args)│Ju
File "/usr/local/lib/python3.9/urllib/request.py", line 641, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 400: Bad Request
I've solved it by regenerating the credentials.json locally on my machine and uploading to the server thinking that it's a one-off event. It worked for a few days and now it stopped working again. So I'm wondering: what should I do so I don't have to regenerate the credentials every few days? My credentials.json looks like below:
{
"email_address": "my.team#gmail.com",
"google_client_id": "74<blabla>0e1feov.apps.googleusercontent.com",
"google_client_secret": "GOCSP<blabla<kOz",
"google_refresh_token": "1//09<blabla>-2_dxZH8"
}
Isn't the point of the refresh token to be used by the library such that I don't have to regenerate this thing by hand?
Can anybody recommend something that can be done? Thanks!
I ran into this same problem, is your app in 'testing' mode with the Google API? Testing tokens have an expiration of 7 days, which is why you had to re-generate your token. I found this answer, but after I changed my status to "In Production" it now gives me an authentication error. Based on this page if you're using Gmail, a production app needs to be verified by Google, but my credential says it doesn't need to be verified and I don't see an option to request verification. Might need to create a new credential?

urllib: Opening a url always gets 429: Too many requests

I just got started with the urllib module. I'm trying to scrape products from supermarkets and there's a website that seems to always respond with an HTTP Error 429: Too many requests. I already did a bit of research on the Stack Overflow and no one seems to have the same problem. My code is as simple as it can get:
>>> import urllib.request
>>> resp = urllib.request.urlopen("https://shop.coles.com.au/a/a-national/product/head-shoulders-shampoo-conditioner-2in1-deep-clean")
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
resp = urllib.request.urlopen("https://shop.coles.com.au/a/a-national/product/head-shoulders-shampoo-conditioner-2in1-deep-clean")
File "C:\Users\thank\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 222, in urlopen
return opener.open(url, data, timeout)
File "C:\Users\thank\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 531, in open
response = meth(req, response)
File "C:\Users\thank\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 640, in http_response
'http', request, response, code, msg, hdrs)
File "C:\Users\thank\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 568, in error
return self._call_chain(*args)
File "C:\Users\thank\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 503, in _call_chain
result = func(*args)
File "C:\Users\thank\AppData\Local\Programs\Python\Python37\lib\urllib\request.py", line 648, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 429: Too Many Requests
I've also tried to modify the user-agent as this answer suggests, but the result is still the same
Can someone explain which default settings inside the urllib module may cause the problem? Or is it because the website blocks bots? Other product pages of the website don't work either.
429 is server asking you to stop. Basically, the web server thinks you are trying to spam or scrape and it doesn't like it. Generally you should honor the server and if there is try after some time with 429 response you should follow it.
If you feel you are wrongly been asked by the server, either you can make sure that your user request is **similar" to the user request generated by an user from the browser, which will include user-agent and all the other information a regular browser would send with the request. If the server is sending you 429 despite that most probably either it has blocked your ip temporarily or permanently. In that you should look how to scrape through multiple ips.

python twitter 404

I'm trying to use twitter-python to connect to twitter's API, and I keep getting this pesky 404 error!
Code is below:
import sys
import twitter
def main():
api = twitter.Api()
statuses = api.GetPublicTimeline()
print [s.user.name for s in statuses]
It should come back with the names of people who've posted status updates on the public timeline, but I get this traceback instead.
Traceback (most recent call last):
File "new.py", line 14, in <module>
main()
File "new.py", line 10, in main
statuses = api.GetPublicTimeline()
File "/usr/lib/pymodules/python2.7/twitter.py", line 1319, in GetPublicTimeline
json = self._FetchUrl(url, parameters=parameters)
File "/usr/lib/pymodules/python2.7/twitter.py", line 2030, in _FetchUrl
url_data = opener.open(url, encoded_post_data).read()
File "/usr/lib/python2.7/urllib2.py", line 400, in open
response = meth(req, response)
File "/usr/lib/python2.7/urllib2.py", line 513, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python2.7/urllib2.py", line 438, in error
return self._call_chain(*args)
File "/usr/lib/python2.7/urllib2.py", line 372, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 521, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: Not Found
If I try to authenticate, all of my requests come back as 401.
Thanks for your help!
on https://code.google.com/p/python-twitter/ they say:
The python-twitter library now only supports oAuth authentication as the Twitter devs have indicated that oAuth is the only method that will be supported moving forward.
api = twitter.Api(consumer_key='consumer_key',
consumer_secret='consumer_secret', access_token_key='access_token', access_token_secret='access_token_secret')
Is that relevant to your problem ?
Twitter is one of the better APIs when it comes to making the oAuth process painless for developers. If you log in to Twitter and go to the developer dashboard at https://dev.twitter.com/apps, you can register a new application (or configure your existing apps).
Viewing the application details will give you an "oAuth Tool" tab, where you'll find all the relevant oAuth values for that app: Consumer Key, Consumer Secret, Access Token, and Access Token Secret.
If you're creating an application that will always authenticate with Twitter as the same user, you can simply hard-code these values into your code or store them in a config file somewhere. If your application needs to authenticate with Twitter on behalf of multiple users (eg, so that it can post statuses on behalf of a user), then you'll need to go through the oAuth dance which is described at https://dev.twitter.com/docs/auth/3-legged-authorization.

HTTP Basic Authentication is failing in python script

I am trying to connect to a REST resource and retrieve the data using Python script (Python 3.2.3). When I run the script I am getting error as HTTP Error 401: Unauthorized. Please note that I am able to access the given REST resource using REST client using Basic Authentication. In the REST Client I have specified the hostname, user and password details (realm is not required).
Below is the code and complete error. Your help is very much appreciated.
Code:
import urllib.request
# set up authentication info
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm=None,
uri=r'http://hostname/',
user='administrator',
passwd='administrator')
opener = urllib.request.build_opener(auth_handler)
urllib.request.install_opener(opener)
res = opener.open(r'http://hostname:9004/apollo-api/nodes')
nodes = res.read()
Error
Traceback (most recent call last):
File "C:\Python32\scripts\get-nodes.py", line 12, in <module>
res = opener.open(r'http://tolowa.wysdm.lab.emc.com:9004/apollo-api/nodes')
File "C:\Python32\lib\urllib\request.py", line 375, in open
response = meth(req, response)
File "C:\Python32\lib\urllib\request.py", line 487, in http_response
'http', request, response, code, msg, hdrs)
File "C:\Python32\lib\urllib\request.py", line 413, in error
return self._call_chain(*args)
File "C:\Python32\lib\urllib\request.py", line 347, in _call_chain
result = func(*args)
File "C:\Python32\lib\urllib\request.py", line 495, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 401: Unauthorized
Try to give the correct realm name. You can find this out for example when opening the page in a browser - the password prompt should display the name.
You can also read the realm by catching the exception that was raised:
import urllib.error
import urllib.request
# set up authentication info
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm=None,
uri=r'http://hostname/',
user='administrator',
passwd='administrator')
opener = urllib.request.build_opener(auth_handler)
urllib.request.install_opener(opener)
try:
res = opener.open(r'http://hostname:9004/apollo-api/nodes')
nodes = res.read()
except urllib.error.HTTPError as e:
print(e.headers['www-authenticate'])
You should get the following output:
Basic realm="The realm you are after"
Read the realm from above and set it in your add_password method and it should be good to go.

Parse.com user login - 404 error

I am fairly inexperienced with user authentication especially through restful apis. I am trying to use python to log in with a user that is set up in parse.com. The following is the code I have:
API_LOGIN_ROOT = 'https://api.parse.com/1/login'
params = {'username':username,'password':password}
encodedParams = urllib.urlencode(params)
url = API_LOGIN_ROOT + "?" + encodedParams
request = urllib2.Request(url)
request.add_header('Content-type', 'application/x-www-form-urlencoded')
# we could use urllib2's authentication system, but it seems like overkill for this
auth_header = "Basic %s" % base64.b64encode('%s:%s' % (APPLICATION_ID, MASTER_KEY))
request.add_header('Authorization', auth_header)
request.add_header('X-Parse-Application-Id', APPLICATION_ID)
request.add_header('X-Parse-REST-API-Key', MASTER_KEY)
request.get_method = lambda: http_verb
# TODO: add error handling for server response
response = urllib2.urlopen(request)
#response_body = response.read()
#response_dict = json.loads(response_body)
This is a modification of an open source library used to access the parse rest interface.
I get the following error:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__
handler.post(*groups)
File "/Users/nazbot/src/PantryPal_AppEngine/fridgepal.py", line 464, in post
url = user.login()
File "/Users/nazbot/src/PantryPal_AppEngine/fridgepal.py", line 313, in login
url = self._executeCall(self.username, self.password, 'GET', data)
File "/Users/nazbot/src/PantryPal_AppEngine/fridgepal.py", line 292, in _executeCall
response = urllib2.urlopen(request)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 126, in urlopen
return _opener.open(url, data, timeout)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 400, in open
response = meth(req, response)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 513, in http_response
'http', request, response, code, msg, hdrs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 438, in error
return self._call_chain(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 372, in _call_chain
result = func(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 521, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 404: Not Found
Can someone point me to where I am screwing up? I'm not quite sure why I'm getting a 404 instead of an access denied or some other issue.
Make sure the "User" class was created on Parse.com as a special user class. When you are adding the class, make sure to change the Class Type to "User" instead of "Custom". A little user head icon will show up next to the class name on the left hand side.
This stumped me for a long time until Matt from the Parse team showed me the problem.
Please change: API_LOGIN_ROOT = 'https://api.parse.com/1/login' to the following: API_LOGIN_ROOT = 'https://api.parse.com/1/login**/**'
I had the same problem using PHP, adding the / at the end fixed the 404 error.

Categories