I'm trying to do a web application using the OAuthlib to login with google, this is what the google object looks like:
google = oauth.remote_app('google',
request_token_url=None,
access_token_method='POST',
request_token_params={'scope': 'email'},
access_token_url='https://accounts.google.com/o/oauth2/token',
authorize_url='https://accounts.google.com/o/oauth2/auth',
consumer_key="my consumer",
consumer_secret="my secret",
base_url='https://www.googleapis.com/oauth2/v1/'
)
The problem I hve is when I get the user information from google, his is my authorization view:
#app.route('/login/authorized/<provider>')
def authorized():
resp = google.authorized_response()
auth_error(resp)
id_token = json.load(resp['id_token'])
login_user(me, True)
return redirect(url_for('index'))
So, what I try to do with the json.load is to decode the information google gives me, in this particular case, the response has an id_token which is a long string that, according to my research, is a json encoded string that when it is decoded, provides all the user information, no matter how much I try I can't seem to find the correct way to decode it, the error I get is:
AttributeError: 'unicode' object has no attribute 'read'
On the json.load line.
EDIT: after decoding the id_token I would then use it to get or create the user in my own database.
I am using Flask and the library is json.
If anyone could explain the correct way to decode the string into a python object I would appreciate it a lot, or if this is not json but some other type of coded string please do tell. Thank you very much in advance.
json.load reads from a file. To decode a JSON string, use json.loads.
However, according to these docs, id_token is not JSON, but a "JSON Web Token".
If you are looking for the "payload", you might try:
payload = json.loads( resp['id_token'].split('.')[1].decode('base64') )
As #this-vidor said my id_token was a JWT not JSON, and I was finally able to decode it using a library called jwt, I used jwt.decode(resp['id_token'], verify=False) and it worked! Just posting this in case anyone had the same problem and wanted a solution. Thank you very much.
For more information on JWT
Related
I'm trying to write a request using Python Requests which sends a request to Docusign. I need to use the legacy authorization header, but unfortunately it seems most documentation for this has been removed. When I send the request I get an error as stated in the title.
From research, I found that special characters in the password can cause this issue, so I've confirmed that my password has no special characters, and that my API key is correct. I am currently sending the header as a stringified dictionary as shown below. I have tried it several other ways, and this seems to be the closest, but it still results in the error. Other ways I've tried include attempting to write out the header as a single string (not forming a dictionary first), but that didn't seem to work any better.
docusign_auth_string = {}
docusign_auth_string["Username"] = docusign_user
docusign_auth_string["Password"] = docusign_password
docusign_auth_string["IntegratorKey"] = docusign_key
docusign_auth_string = str(docusign_auth_string)
headers = {'X-DocuSign-Authentication': docusign_auth_string}
response = requests.post(docusign_url, headers=headers, data=body_data)
The above code returns a 401 with the message, INVALID_TOKEN_FORMAT "The security token format does not conform to expected schema." The header I am sending looks as follows:
{'X-DocuSign-Authentication': "{'Username': 'test#test.com', 'Password': 'xxxxxxxxxx', 'IntegratorKey': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'}"}
When I send the request via Postman, it works just fine. In Postman I enter the header name as X-Docusign-Authentication, and the value as: {"Username":"{{ds_username}}","Password":"{{ds_password}}","IntegratorKey":"{{ds_integrator_key}}"} (subbing the same variable values as in the python code).
Therefore it definitely has something to do with the way Requests is sending the header.
Does anyone know why I might be getting the above error?
I'm able to reproduce this behavior: It looks like DocuSign doesn't accept Single Quotes around the sub-parameters of the x-DocuSign-Authentication header value.
Your example fails:
{'Username': 'test#test.com', 'Password': 'xxxxxxxxxx', 'IntegratorKey': 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'}
This has more success:
{"Username": "test#test.com", "Password": "xxxxxxxxxx", "IntegratorKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}
I'm not familiar enough with Python to advise if there's a different code structure you can follow to use double quotes instead of single. Worst case scenario, you may need to manually set the Header Value to follow that format.
I found a solution to this issue. The response that mentioned double quotes is correct, but in Python I was unable to send a string with the proper format for docusign to understand. Next I found the following Stack overflow question, which ultimately provided the solution:
How to send dict in Header as value to key 'Authorization' in python requests?
I used json.dumps and that resolved the issue. My code is as follows:
docusign_auth_string = {}
docusign_auth_string["Username"] = docusign_user
docusign_auth_string["Password"] = docusign_password
docusign_auth_string["IntegratorKey"] = docusign_key
headers = {"X-DocuSign-Authentication": json.dumps(docusign_auth_string), "Content-Type": "application/json"}
Since you are having success using Postman, it will help to get exactly what is being sent via your request. For this use:
response = requests.get(your_url, headers=your_headers)
x = response.request.headers()
print(x)
This will show you exactly what requests is preparing and sending off. If you post that response here id be happy to help more.
How can I see the entire HTTP request that's being sent by my Python application?
The 2nd answer shows all the possible parameters of your response object.
I'm using Python 3 to get the response from Instagram API using the code below
instagramJSON = xRequest(nextUrl)
print (instagramJSON)
instagramDict = json.load(instagramJSON)
the xRequest method gets the response from the Instagram API URL, when I print the object it looks like a legit JSON object but when I do the json.load method on it I get the following error AttributeError: 'bytes' object has no attribute 'read'
The same code works on Python 2 , I tried to search for it Python docs for Python3 but no luck. Can anyone help me out with this?
Thanks a lot !
If the instagramJSON is a str then you should use json.loads instead of json.load. If instagramJSON is a string then it would have raised the same exception in Python 2 so there may be more going on.
Python JSON documentation
If it is a response generated by urllib.request then the top answer to this question may be relevant.
I am making ajax rest call from ruby and its going to python to do rest call proccess. when i trying to call rest and passing params in json formate, i think its may not passing this as json data.
My ajax call is following:
get '/cnet' do
temp="mynet"
url = URI.parse('http://192.168.1.9:8080/v2.0/networks')
params = {'net_name'=>temp}.to_json
resp = Net::HTTP.post_form(url, params)
resp_text = resp.body
puts resp_text
erb resp_text
end
Python code is following:
#app.route('/v2.0/networks',methods=['POST'])
def net_create():
net_res=request.json
print "======================="
print net_res['net_name']
print "======================="
net_name=net_res['net_name']
when i am trying to read json data from python its giving following error:
File "/network-ui/neutron_plugin.py", line 226, in net_create
net_name=net_res['net_name']
TypeError: 'NoneType' object has no attribute '__getitem__'
I don't know what is exactly happening.
I am following there link for ajax post call:
http://rest.elkstein.org/2008/02/using-rest-in-ruby.html
http://developer.yahoo.com/ruby/ruby-rest.html
Any help much appreciated. Thanks
Don't pass JSON to Net::HTTP. The method requires a simple ruby hash.
In fact, you send POST params - POST params are sent through the HTTP request body, they are not JSON or whatever, just simple strings. This is HTTP basics, so i suggest you read a bit about how things work over this protocol, it will be a lot easier if you understand it.
Regarding the python side, I don't know much Python but if you really need JSON (which i doubt), you will have to somehow parse the params.
I am writing a Python program that feeds a search term to google using the google search API and downloads the first 10 results. I was able to do this in Python 2.6 as follows:
query = urllib.parse.urlencode({'q' : 'searchterm','start' : k},doseq=false)
url = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&%s' \
% (query)
results = urllib.urlopen(url)
resultsjson = json.loads(results.read())
betterResults += resultsjson["responseData"]["results"]
Google's search API returns the results as a json, so I used the above code to download the results into a json of my and parse them into a list (betterResults).
When I switched over to Python 3, my program began throwing exceptions. Apparently, in Python 2.6 the object returned by urlopen() is a file-like object that can be loaded into a json. In Python 3.1, the object returned is an HTTPResponse object, which does contain a read() method, as required by the json specifications, but is a byte object. I was therefore unable to access the information as I had in 2.6.
Is there any way to access the json returned by google? How can I get the results in Python 3 and be able to select which fields I want, as I was able to do with the json?
Thank you very much,
bsg
You'll need to decode the byte object if you want to use it with json.loads
resultjson = json.loads(results.read().decode())
docs also suggest to pass encoding parameter to the loads function:
json.loads(results.read(), encoding=<encoding-type>)
I think Lennart has an explanation how to get the encoding-type.
The object returned by urlopen is file like, you are wrong there. But you use json.loads(), which expects a string. json.load() expects a file like object.
However, json.load() expects the result of the read() method to be a string, while of course the read you get will be bytes, so you need to decode it from bytes to a string first.
So, something like this:
query = urllib.parse.urlencode({'q' : 'searchterm','start' : k},doseq=false)
url = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&%s' \
% (query)
results = urllib.urlopen(url)
encoding = input.getheader('content-type').split('=')[-1]
resultsjson = json.loads(results.read().decode(encoding))
betterResults += resultsjson["responseData"]["results"]
Might work. (I didn't test it).
Really spent a lot of time searching for this. Please need some help.
I am trying to add multilingual feature to my web app framework. For this I am unable to send non ascii characters as JSON. Here is what I am doing
Here is what I get from the database
'\xe0\xa4\xa4\xe0\xa5\x87\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4'
which when I print gives me which is okay
तेस्त
I make the response object
response = {'a':'\xe0\xa4\xa4\xe0\xa5\x87\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\xa4'}
Send the repsonse
import json
sys.stdout.write(json.dumps(response))
This is what it prints
Returns u'{"a": "\u0924\u0947\u0938\u094d\u0924"}'
Any help, pointers will be welcome
Thanks!
Rushabh
Is this your desired output (see ensure_ascii argument for json.dumps)?
sys.stdout.write(json.dumps(response, ensure_ascii=False))
{"a": "तेस्त"}