bad request error 400 google api for translation python - python

calling API and getting the error need to translate from English to France but getting this error so I have used this code but it is not working properly
code:
from __future__ import print_function
__author__ = 'jcgregorio#google.com (Joe Gregorio)'
from googleapiclient.discovery import build
def main():
service = build('translate', 'v2',
developerKey='AIzaSyDRRpR3GS1F1_jKNNM9HCNd2wJQyPG3oN0')
print(service.translations().list(
source='en',
target='fr',
q="flower"
).execute())
if __name__ == '__main__':
main()
Error
Traceback (most recent call last):
File "trail.py", line 19, in <module>
main()
File "trail.py", line 15, in main
q="flower"
File "build/bdist.linux-i686/egg/oauth2client/_helpers.py", line 133, in positional_wrapper
File "build/bdist.linux-i686/egg/googleapiclient/http.py", line 840, in execute
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://www.googleapis.com/language/translate/v2?q=flower&source=en&alt=json&target=fr&key=AIzaSyDRRpR3GS1F1_jKNNM9HCNd2wJQyPG3oN0 returned "Bad Request">

Use the new Google Cloud client library and authorize your API using service account credentials JSON and calling export GOOGLE_APPLICATION_CREDENTIALS=your_service.json instead of using the API key. You can also use default application credentials by calling gcloud auth application-default login.
This is demonstrated in the Google Cloud Translate Python samples which should also help you get started more quickly.
Note the translate API requires billing, as described in the translate quickstart instructions, so be prepared to set that up for your project.

Related

Google Python SDK : google.auth.exceptions.RefreshError: ('No access token in response.',

I am trying to make basic calls for gsuite, ala listing groups. I have poked around quite a bit and have seen several posts suggesting this is a scope issue. However, I have included as many scope paths as I can find that even looked remotely relevant. I still get an exception in the library because there is no "access_token" in the response. There IS an id_token, but nothing labelled "access_token", so the lib throws an exception.
Also, I am pretty sure the account has access to the "group settings API", and many other things.
Banging my head on the desk...
google-api-core==2.10.1
google-api-python-client==2.64.0
google-auth==2.12.0
google-auth-httplib2==0.1.0
google-auth-oauthlib==0.5.3
googleapis-common-protos==1.56.4
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin',
'https://www.googleapis.com/auth/admin.directory.user',
"https://www.googleapis.com/auth/apps.groups.settings",
'https://www.googleapis.com/auth/admin',
'https://www.googleapis.com/auth/apps.groups.settings',
'https://www.googleapis.com/auth/indexing',
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/contacts',
'https://www.googleapis.com/auth/contacts.other.readonly'
'https://www.googleapis.com/auth/contacts.readonly',
'https://www.googleapis.com/auth/directory.readonly',
'https://www.googleapis.com/auth/user.addresses.read',
'https://www.googleapis.com/auth/user.birthday.read',
'https://www.googleapis.com/auth/user.emails.read',
'https://www.googleapis.com/auth/user.gender.read',
'https://www.googleapis.com/auth/user.organization.read',
'https://www.googleapis.com/auth/user.phonenumbers.read',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/admin',
'https://www.googleapis.com/auth/service.management.readonly',
'https://www.googleapis.com/auth/monitoring',
'https://www.googleapis.com/auth/admin.reports.audit.readonly',
'https://www.googleapis.com/auth/admin.reports.usage.readonly',
'https://www.googleapis.com/auth/admin.datatransfer',
'https://www.googleapis.com/auth/admin.datatransfer.readonly',
'https://www.googleapis.com/auth/admin.directory.customer',
'https://www.googleapis.com/auth/admin.directory.customer.readonly',
'https://www.googleapis.com/auth/admin.directory.domain',
'https://www.googleapis.com/auth/admin.directory.domain.readonly',
'https://www.googleapis.com/auth/admin.directory.group',
'https://www.googleapis.com/auth/admin.directory.group.member',
'https://www.googleapis.com/auth/admin.directory.group.member.readonly',
'https://www.googleapis.com/auth/admin.directory.group.readonly',
'https://www.googleapis.com/auth/admin.directory.orgunit',
'https://www.googleapis.com/auth/admin.directory.orgunit.readonly',
'https://www.googleapis.com/auth/admin.directory.resource.calendar',
'https://www.googleapis.com/auth/admin.directory.resource.calendar.readonly',
'https://www.googleapis.com/auth/admin.directory.rolemanagement',
'https://www.googleapis.com/auth/admin.directory.rolemanagement.readonly',
'https://www.googleapis.com/auth/admin.directory.user',
'https://www.googleapis.com/auth/admin.directory.user.alias',
'https://www.googleapis.com/auth/admin.directory.user.alias.readonly',
'https://www.googleapis.com/auth/admin.directory.user.readonly',
'https://www.googleapis.com/auth/admin.directory.user.security',
'https://www.googleapis.com/auth/admin.directory.userschema',
'https://www.googleapis.com/auth/admin.directory.userschema.readonly',
'https://www.googleapis.com/auth/groups',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/cloud-platform.read-only',
'https://www.googleapis.com/auth/apps.groups.migration']
SERVICE_ACCOUNT_FILE = 'privkey.json'
def main():
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = build('admin', 'directory_v1', credentials=credentials)
# this is where the library throws the exception
foobar = service.groups().list().execute()
if __name__ == '__main__':
main()
This is a partial stack trace:
Traceback (most recent call last):
File "/XXXXXXXXXXXXXX/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 294, in jwt_grant
access_token = response_data["access_token"]
KeyError: 'access_token'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "../gsuite_auth_test6.py", line 93, in <module>
main()
File "../gsuite_auth_test6.py", line 90, in main
foobar = service.groups().list().execute()
File "/XXXXXXXXXXXXXX/.local/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/XXXXXXXXXX/.local/lib/python3.7/site-packages/googleapiclient/http.py", line 932, in execute
headers=self.headers,
File "/XXXXXXXXXXXXX/.local/lib/python3.7/site-packages/googleapiclient/http.py", line 191, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File "/XXXXXXXXXXXXXX/.local/lib/python3.7/site-packages/google_auth_httplib2.py", line 209, in request
self.credentials.before_request(self._request, method, uri, request_headers)
File "/XXXXXXXXXXXXXX/.local/lib/python3.7/site-packages/google/auth/credentials.py", line 133, in before_request
self.refresh(request)
File "/XXXXXXXXXXXXXX/.local/lib/python3.7/site-packages/google/oauth2/service_account.py", line 411, in refresh
request, self._token_uri, assertion
File "/XXXXXXXXXXXXXX/.local/lib/python3.7/site-packages/google/oauth2/_client.py", line 299, in jwt_grant
six.raise_from(new_exc, caught_exc)
File "<string>", line 3, in raise_from
google.auth.exceptions.RefreshError: ('No access token in response.', {'id_token': '....'
Your research is right in that this can be caused by wrong scopes but there are more issues here that I will try to address.
I have included as many scope paths as I can find that even looked remotely relevant.
This is a problem. You cannot just throw all scopes to the wall and see what sticks. First you need to have enabled the relevant APIs on your GCP project. In this case you don't actually need the Groups Settings API, instead you need the Directory API, also known as Admin SDK API:
Admin SDK lets administrators of enterprise domains to view and manage resources like user, groups etc. It also provides audit and usage reports of domain.
Next, to know the scopes you can refer to Google's documentation. The groups.list method has the scopes that you need to use to list all Groups in the domain. In this case you can just use https://www.googleapis.com/auth/admin.directory.group.
Also, in the groups.list documentation I linked above you can see that you need to specify either the parameter customer for all groups within the Google Workspace account or domain for just one of its subdomains. You can also just use the my_customer alias to search everything within the account. The Python documentation here has its equivalent for the Python library. All of this means that your line to call groups.list should specify the customer like this:
foobar = service.groups().list(customer="my_customer").execute()
Finally, you seem to be using a service account's credentials. This means that you need to first enable domain-wide delegation for your service account so it can impersonate your user accounts, next, you have to impersonate an admin that already has the privileges to manage groups in the Admin Console. You can refer to the Google OAuth docs to check out how to do this, and here's also a Python sample. Pretty much you can just create a copy of the credentials while specifying the admin account, like this:
delegated_credentials=credentials.with_subject("admin#yourdomain.com")
Here's a sample based on your code that worked for me after taking all of the above into account:
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/admin.directory.group']
SERVICE_ACCOUNT_FILE = 'privkey.json'
def main():
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
#delegate the admin credentials to the service account
delegated_credentials=credentials.with_subject("admin#yourdomain.com")
service = build('admin', 'directory_v1', credentials=delegated_credentials)
# make sure to add the customer parameter per the documentation requirements
foobar = service.groups().list(customer="my_customer").execute()
print(foobar)
if __name__ == '__main__':
main()
As you can see, aside from removing the unnecessary scopes I just changed two lines. First make sure that your GCP and service account configurations are in order and then don't forget to delegate access and specify the customer variable.

How to do authentication check in Python library from Google Cloud Endpoints on GAE standard

I'm trying to implement service-to-service authentication to Google Cloud Endpoints API using Google Service account, but get the following error.
Cannot decode and verify the auth token. The backend will not be able to retrieve user info (.../lib/endpoints_management/control/wsgi.py:596)
Traceback (most recent call last):
File ".../lib/endpoints_management/control/wsgi.py", line 593, in __call__
service_name)
File ".../lib/endpoints_management/auth/tokens.py", line 81, in authenticate
error)
UnauthenticatedException: (u'Cannot decode the auth token', UnicodeDecodeError('ascii', '\xc9\xad\xbd', 0, 1, 'ordinal not in range(128)'))
Value of auth_token variable passed to self.get_jwt_claims(auth_token) is :
ya29.ElmlBB1mwIfrsnURUIQg0Nv6v5UPzFR02miD4w_VywMSlWGDstpmmc5vPsmUqt5rCcho797B1HeEOgT0UBQiVfv9dlsfxSMLRf67SGwX0ceK5uTujj4_tSUXog
Looks like endpoints library is trying to decode auth_token as jwt, but auth_token is not jwt. But maybe I'm wrong. Same problem occurs when I'm trying to test API using API Explorer. This happens with the latest endpoints and also with older version.
Here is my API class:
#endpoints.api(
name='myapi',
version='v1',
api_key_required=True,
auth_level=endpoints.AUTH_LEVEL.REQUIRED,
scopes=(
endpoints.EMAIL_SCOPE,
),
)
class MyApi(remote.Service):
...
And this is how i I'm accessing the API:
credentials = ServiceAccountCredentials.from_json_keyfile_dict(
json.loads(json_keyfile_data),
scopes='https://www.googleapis.com/auth/userinfo.email',
)
service = build(
name, version,
http=credentials.authorize(Http()),
discoveryServiceUrl=discovery_url)
...
Am I doing something from or is there a bug in Python endpoints library?
Google Cloud Endpoints expects JWT id_token, that's the reason why self.get_jwt_claims(auth_token) fails. Here is in-depth explanation of service-to-service authentication: https://cloud.google.com/endpoints/docs/service-to-service-auth.

AppAssertionCredentials fail with 401

Following the instructions here:
https://developers.google.com/accounts/docs/OAuth2ServiceAccount?hl=en_US
I try running this python script on my google compute engine instance:
import httplib2
from googleapiclient.discovery import build
from oauth2client.gce import AppAssertionCredentials
credentials = AppAssertionCredentials("https://www.googleapis.com/auth/datastore")
http = credentials.authorize(httplib2.Http())
service = build('datastore', 'v1beta2', http=http)
x = service.datasets().lookup(body='', datasetId='surferjeff-easybates').execute(http=http)
But I still get this error:
Traceback (most recent call last):
File "C:/Users/surferjeff-easybates/Desktop/test.py", line 8, in <module>
x = service.datasets().lookup(body='', datasetId='surferjeff-easybates').execute(http=http)
File "C:\Python27\lib\site-packages\oauth2client\util.py", line 135, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Python27\lib\site-packages\googleapiclient\http.py", line 723, in execute
raise HttpError(resp, content, uri=self.uri)
HttpError: <HttpError 401 when requesting https://www.googleapis.com/datastore/v1beta2/datasets/surferjeff-easybates/lookup?alt=json returned "Invalid Credentials">
And I have verified that my account has datastore enabled. What am I doing wrong?
The problem is related to a Google simple bug.
When you create a new instance using the cloud console and check the "Allow API access to all Google Cloud services in the same project", you are including this instance in all of the possible cloud scopes.
When you try to view which REST request generated this great functionality (by pressing the "Equivalent REST or command line" button) you see that the instance is generated using one global scope as follows:
"scopes": [
"https://www.googleapis.com/auth/cloud-platform"
]
If you attempt to create this instance using the Google API client (apiclient) with the same scopes you find out that it cannot get valid credentials to use the Datastore service.
The solution resides in the fact that the single scope is apparently not what Google assigns to your instance when you create it through the console.
If you open the instance details after creating it, you find out that it has the following scopes:
"scopes": [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/datastore",
"https://www.googleapis.com/auth/userinfo.email"
]
Once you mention datastore's scope explicitly, things will work as expected.

Dropbox API request token not working with Python 3?

I'm maintaining a Python application using the official Dropbox API. To ask the users to let my application use their Dropbox account, I use a small script using the DropboxSession class, which is clearly the same as the one we can find on this blog post :
# Include the Dropbox SDK libraries
from dropbox import client, rest, session
# Get your app key and secret from the Dropbox developer website
APP_KEY = '******'
APP_SECRET = '******'
# ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
ACCESS_TYPE = 'app_folder'
sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)
request_token = sess.obtain_request_token()
url = sess.build_authorize_url(request_token)
# Make the user sign in and authorize this token
print "url:", url
print "Please visit this website and press the 'Allow' button, then hit 'Enter' here."
# Python 2/3 compatibility
try:
raw_input()
except NameError:
input()
# This will fail if the user didn't visit the above URL
access_token = sess.obtain_access_token(request_token)
#Print the token for future reference
print access_token
While it's perfectly working with Python 2.7.6, it seems to fail because of Dropbox code in Python 3.4 (the raw_input problem having been dealt with). I get this error :
Traceback (most recent call last):
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/session.py", line 285, in _parse_token
key = params['oauth_token'][0]
KeyError: 'oauth_token'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "get_access_token.py", line 12, in <module>
request_token = sess.obtain_request_token()
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/session.py", line 185, in obtain_request_token
self.request_token = self._parse_token(response.read())
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/session.py", line 287, in _parse_token
raise ValueError("'oauth_token' not found in OAuth request.")
ValueError: 'oauth_token' not found in OAuth request.
Long story short, after having studied the faulty code, it seems that the Dropbox code searches for a string dictionary key, despite the fact that in Python 3, those keys become bytestrings (i.e. it lookups 'oauth_token', which isn't here, instead of b'oauth_token', which is here).
However, even after having fixed the code to see if that's the only issue, no luck, I get another error further in the procedure:
Traceback (most recent call last):
File "get_access_token.py", line 25, in <module>
access_token = sess.obtain_access_token(request_token)
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/session.py", line 214, in obtain_access_token
response = self.rest_client.POST(url, headers=headers, params=params, raw_response=True)
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/rest.py", line 316, in POST
return cls.IMPL.POST(*n, **kw)
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/rest.py", line 254, in POST
post_params=params, headers=headers, raw_response=raw_response)
File "/home/scylardor/.virtualenvs/onitu3/lib/python3.4/site-packages/dropbox/rest.py", line 227, in request
raise ErrorResponse(r, r.read())
dropbox.rest.ErrorResponse: [401] 'Unauthorized'
So the faulty functions are sess.obtain_request_token() and sess.obtain_access_token(request_token). And the Python 2.7 version works fine, but I'd like to keep Python 3 compatibility.
So, does anyone know how one's supposed to make it work in Python 3 ? Could it be deliberately broken in order to make people move on to new procedures ? I could have sworn it was working with Python 3, some time ago.
Thank you for your time if you have an idea :)
edit: It seems the Dropbox SDK just isn't fully Python 3-compatible yet. So, I guess there's nothing else to do than to wait for them to update the SDK.
Try to use version 1.6
$ pip install dropbox==1.6
Better than waiting for the SDK to be compatible, you can use (or contribute to and use) the "community" fork, dropbox-py3 (here on github).
(Those quotes are big quotes. For now it's just me coding this, and just the part I need, but everyone's welcome to help. I think it's mainly identifying the few parts that are missing a ".encode" because it's mixing bytes and strings.)

Google Api Auth Http Module Error

I'm working on my first app ever to use Google Api for Calendar. I've read the Google examples at: https://developers.google.com/google-apps/calendar/instantiate
The first time I ran the program below it was successful. I allowed my app to access my Google account and the application made a calendar.dat file with the auth info in my app-directory. After I renamed the filed the code was in the auth stopped working. I have already deleted the file entirely and recreated it from scratch, but the error persists.
I do still get the Google authentication page and can still confirm access, after which I get a message that the authentication flow was completed.
This is the code (standard Google example which I fill in with my app details):
import gflags
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run
FLAGS = gflags.FLAGS
# Set up a Flow object to be used if we need to authenticate. This
# sample uses OAuth 2.0, and we set up the OAuth2WebServerFlow with
# the information it needs to authenticate. Note that it is called
# the Web Server Flow, but it can also handle the flow for native
# applications
# The client_id and client_secret are copied from the API Access tab on
# the Google APIs Console
FLOW = OAuth2WebServerFlow(
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
scope='https://www.googleapis.com/auth/calendar',
user_agent='YOUR_APPLICATION_NAME/YOUR_APPLICATION_VERSION')
# To disable the local server feature, uncomment the following line:
# FLAGS.auth_local_webserver = False
# If the Credentials don't exist or are invalid, run through the native client
# flow. The Storage object will ensure that if successful the good
# Credentials will get written back to a file.
storage = Storage('calendar.dat')
credentials = storage.get()
if credentials is None or credentials.invalid == True:
credentials = run(FLOW, storage)
# Create an httplib2.Http object to handle our HTTP requests and authorize it
# with our good Credentials.
http = httplib2.Http()
http = credentials.authorize(http)
# Build a service object for interacting with the API. Visit
# the Google APIs Console
# to get a developerKey for your own application.
service = build(serviceName='calendar', version='v3', http=http,
developerKey='YOUR_DEVELOPER_KEY')
And this is the output:
Your browser has been opened to visit:
https://accounts.google.com/o/oauth2/auth? (auth url shortened)
If your browser is on a different machine then exit and re-run this
application with the command-line parameter
--noauth_local_webserver
Traceback (most recent call last):
File "C:\Users\Desktop\Google Drive\Code\Python\Rooster\calendar.py", line 2, in <module>
import httplib2
File "C:\Python27\lib\site-packages\httplib2-0.7.6-py2.7.egg\httplib2\__init__.py", line 42, in <module>
import calendar
File "C:\Users\Desktop\Google Drive\Code\Python\Rooster\calendar.py", line 33, in <module>
credentials = run(FLOW, storage)
File "C:\Python27\lib\site-packages\google_api_python_client-1.0-py2.7.egg\oauth2client\util.py", line 120, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Python27\lib\site-packages\google_api_python_client-1.0-py2.7.egg\oauth2client\tools.py", line 169, in run
credential = flow.step2_exchange(code, http=http)
File "C:\Python27\lib\site-packages\google_api_python_client-1.0-py2.7.egg\oauth2client\util.py", line 120, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Python27\lib\site-packages\google_api_python_client-1.0-py2.7.egg\oauth2client\client.py", line 1128, in step2_exchange
http = httplib2.Http()
AttributeError: 'module' object has no attribute 'Http'
The problem is that in your run directory you have the file named calendar.py. When Google's httplib2 wants to import a standard calendar module it gets the local one instead. In the local one it executes it to perform the import. But because httplib2 is not yet fully imported the calendar.py code is not working properly.
Just rename the calendar.py to something like myCalendar.py.

Categories