GoogleOAuth2 Auth Failure "unauthorized_client"/ Python GoogleAdWord API - python

Iam trying to accsess OAuth2 in Python (the code is the same as http://code.google.com/p/google-api-ads-python/source/browse/trunk/examples/adspygoogle/adwords/v201302/misc/use_oauth2.py?spec=svn139&r=139):
flow = OAuth2WebServerFlow(client_id='XXX',
client_secret='YYY',
scope='https://adwords.google.com/api/adwords',
user_agent='ZZZ')
authorize_url = flow.step1_get_authorize_url('urn:ietf:wg:oauth:2.0:oob')
code = raw_input('Code: ').strip()
credential = None
try:
credential = flow.step2_exchange(code) #<- error
except FlowExchangeError, e:
sys.exit('Authentication has failed: %s' % e)
This produces a "socket.error: [Errno 10054]" error at the step2_exchange and Python cuts off the excact message.
So after checking the key with OAuthplayground (to get an better errormsg) i get this Error:
HTTP/1.1 400 Bad Request
Content-length: 37
X-xss-protection: 1; mode=block
X-content-type-options: nosniff
X-google-cache-control: remote-fetch
-content-encoding: gzip
Server: GSE
Via: HTTP/1.1 GWA
Pragma: no-cache
Cache-control: no-cache, no-store, max-age=0, must-revalidate
Date: Thu, 06 Jun 2013 13:54:29 GMT
X-frame-options: SAMEORIGIN
Content-type: application/json
Expires: Fri, 01 Jan 1990 00:00:00 GMT
{
"error" : "unauthorized_client"
}
I checked that client_id (for installed Apps) and client_secret are Identical with the one specified in the Google API Console (https://code.google.com/apis/console/).
If i do the whole proces over OAuthPlayground it will work but if i try to use a Token created by playground the App fails also.
Anyone knows how to fix it?

Fixed it. Iam behind a proxy which makes lets the step1 Auth through but apparently not the step2 auth. So a simple
h = httplib2.Http(proxy_info = httplib2.ProxyInfo PROXY DATA .....)
flow.step2_exchange(code, h)
fixed it.

There is an example of how to configure the proxy_info in httplib2 is in https://code.google.com/p/httplib2/wiki/Examples
which says:
import httplib2
import socks
httplib2.debuglevel=4
h = httplib2.Http(proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8000))
r,c = h.request("http://bitworking.org/news/")
However, I've found with the latest httplib2, a cleaned-up socks module comes with it, such that you really want to do something more like:
import httplib2
ht = httplib2.Http(proxy_info = httplib2.ProxyInfo(httplib2.socks.PROXY_TYPE_HTTP, 'name_or_ip_of_the_proxy_box', proxy_port)
flow.step2_exchange(code, ht)
also, you want to be using a version of oauth2client >= 1.0beta8 which requires the version of httplib2 >= 0.7.4 which is where the support for HTTP proxy was cleaned up in both packages.

Related

Response content shorter than Content-Length

I'm doing a FastAPI app, with a function that authenticates to a CouchDB instance. In order to request Couchdb, I use the (yet unmaintained) library python-couchdb.
Here is the relevant portion of code that illustrates my issue:
from fastapi import FastAPI
from couchdb import http
resource = http.Resource(url, http.Session())
from couchdb import Unauthorized
from pydantic import BaseModel
app = FastAPI()
class RegisteredUser(BaseModel):
email: str
password: str
#app.post("/login")
async def log_user(user: RegisteredUser):
# some email format verifications here
# ...
try:
status, headers, _ = resource.post_json('_session', {
'name': user.email,
'password': user.password,
})
except Exception as e:
if isinstance(e, Unauthorized):
return 403
else:
return 500
# tests
print(headers)
The headers look like:
Cache-Control: must-revalidate
Content-Length: 54
Content-Type: application/json
Date: Sat, 08 Aug 2020 19:19:49 GMT
Server: CouchDB/3.1.0 (Erlang OTP/22)
Set-Cookie: AuthSession=am9zZWJvdmVAam9zZWJvdmUuY29tOjVGMkVGQUQ2Op-UUD22VvdxYzbMNp92e30Er_z0; Version=1; Expires=Sat, 08-Aug-2020 20:59:50 GMT; Max-Age=6000; Path=/; HttpOnly
At this point (if no error raised), I'd like to send back to the (browser) client the cookie that CouchDb provides. Something like:
...
# tests
print(headers)
if status == 200 and 'Set-Cookie' in headers:
return JSONResponse(content=True, headers=headers)
else:
return status
I'm not used to sessions-cookie and I'm not sure if I should send back the full headers or just the headers['Set-Cookie'] part
Whatever I do, I end up with the same error message
RuntimeError: Response content shorter than Content-Length
Would you mine to explain to me what the error is saying, and how I can solve my case? Ty!
Found this SO thread but no clue neither FastAPI middleware peeking into responses
Here is one solution:
if status == 200 and 'Set-Cookie' in headers:
return JSONResponse(content=True, headers={
'Set-Cookie' : headers['Set-Cookie']
})
else:
return status
Ty #HernánAlarcón

Discrepency between curl results and Python requests results

I am querying the New Relic API, and trying to pull CPU utilization fron the metrics that they provide. When I run the following curl command (after exporting the correct proxy settings), I see the following information (which contains the percentage value that I want) -
curl -X GET "https://api.newrelic.com/v2/applications/140456413/hosts/21044947/metrics/data.json" -H "X-Api-Key:myapikey" -i -d 'names[]=CPU/User+Time&values[]=percent&summarize=true&from=2018-07-15 16:22:30&to=2018-07-16 16:22:30'
HTTP/1.0 200 Connection Established
Proxy-agent: Apache
HTTP/1.1 200 OK
Server: openresty
Date: Tue, 17 Jul 2018 11:53:22 GMT
Content-Type: application/json
Content-Length: 290
Connection: keep-alive
Status: 200 OK
X-UA-Compatible: IE=Edge,chrome=1
ETag: "a35b451e27a49d0d5f4e16715429a17d"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: f4f8675f095aba80d5e089fbcbf1b172
X-Runtime: 0.168283
X-Rack-Cache: miss
{"metric_data":{"from":"2018-07-15T16:22:30+00:00","to":"2018-07-16T16:22:30+00:00","metrics_not_found":[],"metrics_found":["CPU/User Time"],"metrics":[{"name":"CPU/User Time","timeslices":[{"from":"2018-07-15T16:22:00+00:00","to":"2018-07-16T16:22:00+00:00","values":{"percent":9.52}}]}]}}
However, when I try to implement it inside of the Python requests module, the "Percent" value that I am interested in seeing is returning 0. This is my code to call it -
options = {"names[]": "CPU/User+Time", "values[]": "percent", "summarize": "true", "from": str(end_date), "to": str(start_date - datetime.timedelta(hours=6))}
path = "applications/140456413/hosts/" + server_id + "/metrics/data.json"
api_key = "myapikey"
headers = {'X-Api-Key': api_key}
url = "https://api.newrelic.com/v2/" + path
r = requests.get(url, headers=headers, data=options, proxies=myproxy.proxies)
This is what I get instead (notice the percent value is now 0) -
{u'metric_data': {u'metrics': [{u'timeslices': [{u'values': {u'percent': 0}, u'to': u'2018-07-17T01:35:00+00:00', u'from': u'2018-07-16T07:35:00+00:00'}], u'name': u'CPU/User+Time'}], u'to': u'2018-07-17T01:35:59+00:00', u'metrics_found': [u'CPU/User+Time'], u'from': u'2018-07-16T07:35:59+00:00', u'metrics_not_found': []}}
How can I adjust the python request to match the same output as the curl command? We were originally passing in options inside of the "options" variable using ='s instead of key/value pairs, but the requests module would not process them in this format.
These were the docs pages I referencesd -
https://docs.newrelic.com/docs/apis/rest-api-v2/requirements/specifying-time-range-v2
https://docs.newrelic.com/docs/apis/rest-api-v2/application-examples-v2/get-average-cpu-usage-host-app
https://docs.newrelic.com/docs/apis/rest-api-v2/getting-started/introduction-new-relic-rest-api-v2#examples
Thanks.
Change the options a bit:
"values[]": "percent"
to:
"values": ["percent"]

URLError doesn't return json body

I have built a REST interface. On '400 Bad Request' it returns a json body with specific information about the error.
(Pdb) error.code
400
Python correctly throws a URLError with these headers
(Pdb) print(error.headers)
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 20 Aug 2016 13:01:05 GMT
Connection: close
Content-Length: 236
There is a content of 236 char, but I cannot find a way to read the body.
I can see the extra information using DHC chrome plugin
{
"error_code": "00000001",
"error_message": "The json data is not in the correct json format.\r\nThe json data is not in the correct json format.\r\n'Execution Start Time' must not be empty.\r\n'Execution End Time' must not be empty.\r\n"
}
However, I cannot find a way in Python to read the body
Here are some of the things I have tried and what was returned.
(Pdb) len(error.read())
0
error.read().decode('utf-8', 'ignore')
''
(Pdb) error.readline()
b''
I found that this works the first time it is called, but does not work if called again.
error.read().decode('utf-8')

Uploading file using socket and Put with Python

I am trying to upload a file to the server in a simple way and I am getting the following error:
HTTP/1.1 411 Length Required
Content-Type: text/html
Date: Wed, 01 Jul 2015 03:05:33 GMT
Connection: close
Content-Length: 24
Length Required
I tried to insert length in different parts and looks like is not working, any suggestions?
import socket
import httplib
import os.path
target_host = "192.168.1.1"
target_port = 80
total_size = os.path.getsize('/root/test.html')
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client.connect((target_host,target_port))
client.send("PUT /root/test.html HTTP/1.1\r\nHost:192.168.1.1\r\n\r\n" )
response = client.recv(4096)
print response
Have you tried implementing this with requests?
You could easily specify the missing content-length header that is causing your error.
Check out this answer: Is there any way to do HTTP PUT in python
Here's an example using the requests library:
payload = {'username': 'me', 'email': 'me#me.com'}
>>> r = requests.put("http://somedomain.org/endpoint", data=payload)

How can I view error messages with pycurl?

I have the following pycurl code:
curl = pycurl.Curl()
foo = StringIO()
curl.setopt(pycurl.WRITEFUNCTION, foo.write)
curl.setopt(pycurl.POST, 1)
curl.setopt(pycurl.URL, finalURL)
curl.setopt(pycurl.POSTFIELDS, encodedArgs)
curl.perform()
responseCode = curl.getinfo(pycurl.RESPONSE_CODE)
effectiveURL = curl.getinfo(pycurl.EFFECTIVE_URL)
curl.close()
When the command line curl command comes back I see:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=UTF-8
Content-Length: 216
Date: Thu, 06 Jan 2011 15:49:36 GMT
Some XML Error Here: Something you are trying to do is not permitted.
But I don't see this from pycurl.
How can I extract this alert/error message when using pycurl?
The response from the server is written using the curl option pycurl.WRITEFUNCTION.
In your case, since you are passing it a StringIO object, the response data should be in the foo variable: foo.getvalue()
Reference: http://pycurl.sourceforge.net/doc/curlobject.html

Categories

Resources