I'm trying to get information from the Gimmebar API (redirects to the access token step) and having problems with the last step exchanging the access token for the data.
#getting access token successfully before this
post_url = '/tags'
headers = {'Authorization': 'Bearer %s' % access_token}
query = '/collections'
full_url = '%s%s%s' % (base_url, post_url, query)
req = urllib2.Request(full_url, headers=headers)
response = urllib2.urlopen(req)
the_page = response.read()
It breaks at the urllib2.Request and I'm getting an error that I'm not sure what to do with:
No exception supplied
Exception
Location: /System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/urllib2.py
in http_error_default, line 510
Here is the view so you can see how I got to step5...
Related
Some background. This code takes a data from a data collection script and then posts it to a secured REST API in Django. I have an api key generated and it is the only line in the file api.key. I also have the url to post to in the file post.url (it looks like http://example.com/api/ and then I concatenate the proper api node name on the end).
The code is below for my solar data api node (posts data collected from solar panels)
import gather_solar as gs
import requests
import json
import os
def post_solar():
print("DEBUG: start solar")
data = gs.gather_solar()
api_key = None
url = None
try:
here = os.path.dirname(os.path.abspath(__file__))
filename = os.path.join(here, 'api.key')
file = open(filename, "r")
api_key = file.readline()
api_key.replace('\n', '')
except Exception as e:
print("ERROR: " + str(e))
try:
here = os.path.dirname(os.path.abspath(__file__))
filename = os.path.join(here, 'post.url') #server will use different url
file = open(filename, "r")
url = file.readline()
url.replace('\n', '')
except Exception as e:
print("ERROR: " + str(e))
if api_key is not None and url is not None:
authorization = "Token " + api_key
authorization.replace('\n', '')
headers = {
'Content-Type': 'application/json; charset=UTF-8',
'Authorization': authorization
}
json_data = json.dumps(data)
url += "solar/"
url.replace('\n', '')
print(url)
req = requests.Request('POST', url, data=json_data, headers=headers)
prepared = req.prepare()
print("DEBUG: POST Headers: " + str(prepared.headers))
print("DEBUG: POST Body: " + str(prepared.body))
s = requests.Session()
response = s.send(prepared)
print("DEBUG: Response Code: " + str(response.status_code))
print("DEBUG: Response Headers: " + str(response.headers))
print("DEBUG: Response Data: " + str(response.json()))
else:
print("DEBUG: Error with API key")
print("DEBUG: end solar")
I am running code on an ubuntu server via AWS and have Apache 2 setup and running. However, whenever I run this script, I get an error saying that my token is invalid and it shows the token as "Token abcd...abcd\n" . This is especially frustrating because I don't have this issue when I run the script locally (visual studio code on Win10) As you can see I have tried to remove any newlines wherever possible but it doesn't seem to be helping. Any help would be greatly appreciated
replace() does not change the string (strings are immutable); it returns a new string. So:
api_key = file.readline()
api_key.replace('\n', '')
leaves the \n on api_key and you are ignoring the new string returned by replace().
You could just string the line before assignment:
api_key = file.readline().strip()
#app.route('/login')
def showLogin():
state = ''.join(random.choice(string.ascii_uppercase + string.digits)
for x in xrange(32))
login_session['state'] = state
# return "The current session state is %s" % login_session['state']
return render_template('login.html', STATE=state)
#app.route('/gconnect', methods=['POST'])
def gconnect():
# Validate state token
if request.args.get('state') != login_session['state']:
response = make_response(json.dumps('Invalid state parameter.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
# Obtain authorization code
code = request.data
try:
# Upgrade the authorization code into a credentials object
oauth_flow = flow_from_clientsecrets('client_secrets.json', scope='')
oauth_flow.redirect_uri = 'postmessage'
credentials = oauth_flow.step2_exchange(code)
except FlowExchangeError:
response = make_response(
json.dumps('Failed to upgrade the authorization code.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
# Check that the access token is valid.
access_token = credentials.access_token
url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s'
% access_token)
h = httplib2.Http()
result = json.loads(h.request(url, 'GET')[1])
# If there was an error in the access token info, abort.
if result.get('error') is not None:
response = make_response(json.dumps(result.get('error')), 500)
response.headers['Content-Type'] = 'application/json'
return response
# Verify that the access token is used for the intended user.
gplus_id = credentials.id_token['sub']
if result['user_id'] != gplus_id:
response = make_response(
json.dumps("Token's user ID doesn't match given user ID."), 401)
response.headers['Content-Type'] = 'application/json'
return response
# Verify that the access token is valid for this app.
if result['issued_to'] != CLIENT_ID:
response = make_response(
json.dumps("Token's client ID does not match app's."), 401)
print "Token's client ID does not match app's."
response.headers['Content-Type'] = 'application/json'
return response
stored_access_token = login_session.get('access_token')
stored_gplus_id = login_session.get('gplus_id')
if stored_access_token is not None and gplus_id == stored_gplus_id:
response = make_response(json.dumps('Current user is connected'), 200)
response.headers['Content-Type'] = 'application/json'
return response
# Store the access token in the session for later use.
login_session['access_token'] = credentials.access_token
login_session['gplus_id'] = gplus_id
# Get user info
userinfo_url = "https://www.googleapis.com/oauth2/v1/userinfo"
params = {'access_token': credentials.access_token, 'alt': 'json'}
answer = requests.get(userinfo_url, params=params)
data = answer.json()
login_session['username'] = data['name']
login_session['picture'] = data['picture']
login_session['email'] = data['email']
# See if a user exists, if it doesn't make a new one
user_id = getUserID(login_session['email'])
if not user_id:
user_id = createUser(login_session)
login_session['user_id'] = user_id
output = ''
output += '<h1>Welcome, '
output += login_session['username']
output += '!</h1>'
output += '<img src="'
output += login_session['picture']
output += ' " style = "width: 300px; height: 300px;border-radius: 150px;'
output += '-webkit-border-radius: 150px;-moz-border-radius: 150px;"> '
print "done!"
return output
I ran this OAuth code on my local machine. It worked but on Amazon Lightsail instance it gave the following error:
*Error: invalid_request Permission denied to generate login hint for target domain.
I even corrected my Redirect Uris and JAVA Script Origins to .com but it still gives the same error even on erasing the cookies.
I'am trying to generate unique URLs, and then check this in https://goo.gl/. My code in python:
import requests
import json
def goo_shorten_url(url):
post_url = 'https://www.googleapis.com/urlshortener/v1/url?key=xxxxxxxxxxxxxxxxxxxx'
payload = {'longUrl': url}
headers = {'content-type': 'application/json'}
r = requests.post(post_url, data=json.dumps(payload), headers=headers)
print r.text
goo_shorten_url('http://www.google.com')
However I can't understand how to modifies my code and configure a token in order to get this unique URLs
I am trying to take some working code and change from urlib2 to requests.
The original code provides basic login information of username, password and posts the KEY and SECRET in the header of the urllib2 request. The following code is my attempt to change to using the requests module and gain some functionality for making additional API calls. I have tried dozens of combinations and all return a code 400. Apparently, my requests code does not successfully furnish the needed information to return a 200 response and provide the needed authorization token.
## Import needed modules
import urllib2, urllib, base64
import httplib
import requests
import json
## initialize variables
KEY = "7f1xxxx-3xxx-4xxx-9a7f-8be66839dede"
SECRET = "45xxxxxx-45xxx-469a-9ae9-a7927a76cfeb"
userName = "my-email#xxx.com"
passWord = "mypassword"
URL = "https://company.com/auth/token"
token = None
sessionid = None
DATA = urllib.urlencode({"grant_type":"password",
"username":userName,
"password":passWord})
base64string = base64.encodestring('%s:%s' % (KEY, SECRET)).replace('\n', '')
request = urllib2.Request(URL, DATA)
request.add_header("Authorization", "Basic %s" % base64string)
result = urllib2.urlopen(request)
token = result.read()
print token
This returns my authorization token and all is well. I can pass the token to the authorization server and have full access to the api for interacting with the database. Below is the attempt to use requests and have the added functions it provides.
client = requests.session()
payload = {"grant_type":"password",
"username":userName,
"password":passWord,
"applicationId": KEY
}
headers = {'content-type':'application/json',
"grant_type":"password",
"username":userName,
"password":passWord,
'applicationsId': KEY,
'Authorization': base64string,
'token': token,
'sessionid': sessionid
}
response = client.post(URL, params = payload, headers=headers)
token = response.content
print token
{"error":"invalid_request"}
print response
<Response [400]>
If you want to use basic auth you should use the method from requests..
Your post should look like
response = client.post(
URL,
params = payload,
headers=headers,
auth=HTTPBasicAuth(
KEY,
SECRET
))
Somewhere in a post a contributor to another question mentioned some items actually needed to be in the body of the request not in the header. I tried various combos and the following solved the 400 response and accomplished my goals.
data = {"grant_type":"password",
"username":userName,
"password":passWord,
"applicationId": KEY
}
headers = {'Authorization': "Basic %s" % base64string,
'token': token
}
response = client.post(URL, data = data, headers=headers)
token = response.text
print token
I have the following code.
params = {'client_id':settings.SOCIAL_AUTH_INSTAGRAM_KEY,
'client_secret':settings.SOCIAL_AUTH_INSTAGRAM_SECRET,
'aspect':'media',
'object':'tag',
'object_id':instance.hashtag,
'callback_url':
'http://subdomain.domain.net:8000/campaigns/hook'}
response = requests.post('https://api.instagram.com/v1/subscriptions',
data=params)
And I get response
'{"meta":{"error_type":"APISubscriptionError","code":400,"error_message":"Invalid
response"}}'
My domain is reachable from outside. Any ideas?
This was because Instagram sends a GET request to my callback_url
and wants me to response with hub.challenge parameter like below
if self.request.GET:
response = request.GET.get('hub.challenge')
return HttpResponse(response)