Google Cloud API 403 - Insufficient Permission - python

I would like to extract the reporting data of our mobile apps from Google Play Console.
According to this documentation, we have to use SignedJwtAssertionCredentials to authenticate. After some errors and research it seems that the code snippet in the doc is kind of outdated (since SignedJWTAssertionCredentials is not available anymore). Instead we tried the following to automatically download the reports:
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
scopes = ['https://www.googleapis.com/auth/analytics.readonly']
key_file_location = 'files/access_token/mykeyfile.json'
credentials = ServiceAccountCredentials.from_json_keyfile_name(key_file_location, scopes)
cloud_storage_bucket = 'pubsite_prod_rev_123456789'
report_to_download = 'installs/installs_com.someapp.etc.etc_2021*'
storage = build('storage', 'v1', credentials=credentials)
print( storage.objects().get(bucket = cloud_storage_bucket,object = report_to_download).execute())
Now the problem is, that we receive the following error message:
Traceback (most recent call last):
File "C:\Users\dev\dev\z_10_ext_google_play_store.py", line 30, in <module>
print( storage.objects().get(bucket = cloud_storage_bucket,object = report_to_download).execute())
File "D:\Software\Python\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "D:\Software\Python\lib\site-packages\googleapiclient\http.py", line 938, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://storage.googleapis.com/storage/v1/b/pubsite_prod_rev_123456789/o/installs%2Finstalls_com.someapp.etc.etc_2021%2A?alt=json returned "Insufficient Permission". Details: "[{'message': 'Insufficient Permission', 'domain': 'global', 'reason': 'insufficientPermissions'}]">
Does anyone have an idea? Our service account even has admin rights in play console (which normally would be to much..)
UPDATE
As DaImTo pointed out, I was missing some scopes which lead me to a different line of scope definition:
scopes = ['https://www.googleapis.com/auth/analytics.readonly', 'https://www.googleapis.com/auth/devstorage.read_only'
,'https://www.googleapis.com/auth/cloud-platform.read_only']
But I still receive some errors, now because of the missing access token which is weird because the .json file contains everything necessary:
Traceback (most recent call last):
File "C:\Users\andre\Desktop\DAWSE\z_10_ext_google_play_store.py", line 33, in <module>
print( storage.objects().get(bucket = cloud_storage_bucket,object = report_to_download).execute())
File "D:\Sonstige Programme\Python\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "D:\Sonstige Programme\Python\lib\site-packages\googleapiclient\http.py", line 923, in execute
resp, content = _retry_request(
File "D:\Sonstige Programme\Python\lib\site-packages\googleapiclient\http.py", line 191, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File "D:\Sonstige Programme\Python\lib\site-packages\oauth2client\transport.py", line 159, in new_request
credentials._refresh(orig_request_method)
File "D:\Sonstige Programme\Python\lib\site-packages\oauth2client\client.py", line 749, in _refresh
self._do_refresh_request(http)
File "D:\Sonstige Programme\Python\lib\site-packages\oauth2client\client.py", line 785, in _do_refresh_request
self.access_token = d['access_token']
KeyError: 'access_token'

You appear to be using the objects.get method
The authenticated user must have sufficient permission to use this method. To start with i would ensure your service account has access.
After that i would check your scopes you are currently only loading the scope for google analytics api.
scopes = ['https://www.googleapis.com/auth/analytics.readonly']
This scope will not grant you access to the google cloud storage objects get method. For that you need to use one of the google cloud storage scopes

Related

google.auth.exceptions.RefresError: 'No access token in response.'

Environment details
OS type and version:
Python version: 3.9.0
pip version: 22.0.4
google-api-python-client version: 2.48.0
Description
Hi, I'm running into an error when trying to fetch the Google Play Console reports of our mobile apps (such as installations, errors etc.). I first tried with this manual but it seems to be outdated and didn't work. So after some research I changed it similar to this one, that it fits to the current google api (see code snippet below).
Steps I have done:
Created a project on "console.cloud.google.com"
Created the service account
Created the json key file
Invited the service account on play.google.com/console and gave him full admin rights (normally "see app information and download bulk reports" should be enough)
Added the role "Storage Object Viewer" to the Service account in https://console.cloud.google.com/iam-admin/iam?authuser=1&project=myproject
waited for 24h to make sure there are no errors because of syncs or so.
(I anonymized some of the values below).
Code example
from googleapiclient.discovery import build
from google.oauth2 import service_account
scopes = ['https://www.googleapis.com/auth/devstorage.read_only','https://www.googleapis.com/auth/cloud-platform.read_only']
key_file_location = 'files/access_token/mykeyfile.json'
cloud_storage_bucket = r'pubsite_prod_rev_00123456789'
report_to_download = 'installs/installs_com.my.app_202201_country.csv'
creds = service_account.Credentials.from_service_account_file(key_file_location,scopes=scopes)
service = build('storage','v1', credentials=creds)
print(service.objects().get(bucket = cloud_storage_bucket, object= report_to_download).execute())
Stack trace
Traceback (most recent call last):
File "C:\Users\myuser\project\z_10_ext_google_play_store.py", line 46, in <module>
print(service.objects().get(bucket = cloud_storage_bucket, object= report_to_download).execute())
File "D:\Programs\Python\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "D:\Programs\Python\lib\site-packages\googleapiclient\http.py", line 923, in execute
resp, content = _retry_request(
File "D:\Programs\Python\lib\site-packages\googleapiclient\http.py", line 191, in _retry_request
resp, content = http.request(uri, method, *args, **kwargs)
File "D:\Programs\Python\lib\site-packages\google_auth_httplib2.py", line 209, in request
self.credentials.before_request(self._request, method, uri, request_headers)
File "D:\Programs\Python\lib\site-packages\google\auth\credentials.py", line 133, in before_request
self.refresh(request)
File "D:\Programs\Python\lib\site-packages\google\oauth2\service_account.py", line 410, in refresh
access_token, expiry, _ = _client.jwt_grant(
File "D:\Programs\Python\lib\site-packages\google\oauth2\_client.py", line 199, 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': 'eyJ...'})
I hope that I provided enough information and I'm sorry in advance if I made a stupid mistake.

How to read data from Google Sheets in Python

I have a Google Sheet https://docs.google.com/spreadsheets/d/1Ycg7zTxds9DZnDvTrFcyNNKuTUxg6Yy6WF0a8Wc02WQ/edit#gid=0 I can read only. I need to read it in Python. I uploaded a video of what I am doing https://youtu.be/4cK0g9Bm_7w
import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ["https://docs.google.com/spreadsheets/d/1Ycg7zTxds9DZnDvTrFcyNNKuTUxg6Yy6WF0a8Wc02WQ/edit#gid=0",
"https://docs.google.com/spreadsheets/d/1Ycg7zTxds9DZnDvTrFcyNNKuTUxg6Yy6WF0a8Wc02WQ/edit?usp=sharing"]
creds = ServiceAccountCredentials.from_json_keyfile_name("creds.json", scope)
client = gspread.authorize(creds)
sheet = client.open("[XO] developer test data").sheet1
I have an error:
Traceback (most recent call last):
File "C:\Python379\lib\site-packages\google\oauth2\_client.py", line 196, 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 "E:/Прогрммирование/Последние алгоритмы/Git/GoogleSheets/sheets.py", line 11, in <module>
sheet = client.open("[XO] developer test data").sheet1
File "C:\Python379\lib\site-packages\gspread\client.py", line 121, in open
self.list_spreadsheet_files(title),
File "C:\Python379\lib\site-packages\gspread\client.py", line 98, in list_spreadsheet_files
res = self.request('get', url, params=params).json()
File "C:\Python379\lib\site-packages\gspread\client.py", line 70, in request
headers=headers,
File "C:\Python379\lib\site-packages\requests\sessions.py", line 546, in get
return self.request('GET', url, **kwargs)
File "C:\Python379\lib\site-packages\google\auth\transport\requests.py", line 478, in request
self.credentials.before_request(auth_request, method, url, request_headers)
File "C:\Python379\lib\site-packages\google\auth\credentials.py", line 133, in before_request
self.refresh(request)
File "C:\Python379\lib\site-packages\google\oauth2\service_account.py", line 377, in refresh
request, self._token_uri, assertion
File "C:\Python379\lib\site-packages\google\oauth2\_client.py", line 199, 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': 'eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5ZmUyYTdiNjc5NTIzOTYwNmNhMGE3NTA3OTRhN2JkOWZkOTU5NjEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9zcHJlYWRzaGVldHMvZC8xWWNnN3pUeGRzOURabkR2VHJGY3lOTkt1VFV4ZzZZeTZXRjBhOFdjMDJXUS9lZGl0I2dpZD0wLGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFZY2c3elR4ZHM5RFpuRHZUckZjeU5OS3VUVXhnNll5NldGMGE4V2MwMldRL2VkaXQ_dXNwPXNoYXJpbmciLCJhenAiOiJhY2MxMC0yMjhAcHJvamVjdC0xMC0zMTc0MDIuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJlbWFpbCI6ImFjYzEwLTIyOEBwcm9qZWN0LTEwLTMxNzQwMi5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE2MjQxNjA4NTIsImlhdCI6MTYyNDE1NzI1MiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTA4OTUzMjg5ODAwOTQ4MzEyOTgxIn0.RYEt9eTvaCXSRPH-ddjB4s5wCE60tt2w-ZgL2aaeBT8ZTyKtlDbpMKV1zG8XRkxqCLs_xde-TEwTZoRQ8OKuJGQIZr6U8mSmqjW7xlhz5cvDLL03o-muks06FbLsgAFE2yEow5EdFcEL8hKt8LGuFoQWuiNWNT-sd-Z-vJMG0-XC6twrYgYp59tdmxCCG3MEprKbtgHpwAWHPoWjybKkETGXVnv17DSV99LIXY9FIzQVV4FV4reBn_4sgcT4y6IcbHqe6hpt4joEDYBsVxImzKk7IJjJfsRCg-kGpfc1yOC831qbupMlF45H75XMq9WWmnrn3Su4YFIBTugUxrMpdA'})
Issues:
You are not providing valid scopes. A scope is not the URL of a file you want to access. A scope determines what actions an API client can make, like reading user's spreadsheets, or reading and writing user's spreadsheets; it doesn't refer to specific files. Here you can see a list of the existing scopes in Sheets API: Authorizing requests with OAuth 2.0.
oauth2client is deprecated. Consider using google-auth instead.
Code sample:
import gspread
from google.oauth2.service_account import Credentials
scopes = [
'https://www.googleapis.com/auth/spreadsheets' # Change according to your preferences
]
credentials = Credentials.from_service_account_file(
'creds.json',
scopes=scopes
)
client = gspread.authorize(creds)
sheet = client.open("[XO] developer test data").sheet1
Notes:
gspread is not officially supported by Google. Here is the official library. And here is the corresponding quickstart for Sheets API.
I am assuming that creds.json refers to valid service account credentials.
If you store creds.json to ~/.config/gspread/creds.json, you should be able to do this, according to the gspread documentation:
import gspread
client = gspread.service_account()
sheet = client.open("[XO] developer test data").sheet1
Reference:
google.oauth2.service_account module

Speech-to-text: google.api_core.exceptions.PermissionDenied: 403

I am trying to use Google speech-to-text service, according to https://googleapis.github.io/google-cloud-python/latest/speech/index.html
I have created project, uploaded audio to gs: cloud, added permissions, downloaded json file named My First Project-7bb85a480131.json. https://console.cloud.google.com/storage/browser/mybucket?project=my-project
that is my file:
import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="/home/joo/Документы/LocalRepository/robotze/My First Project-7bb85a480131.json"
from google.cloud import speech
client = speech.SpeechClient()
audio = speech.types.RecognitionAudio(
uri='gs://zaudio/audio.mp3')
config = speech.types.RecognitionConfig(
encoding=speech.enums.RecognitionConfig.AudioEncoding.LINEAR16,
language_code='ru-RU',
sample_rate_hertz=44100)
operation = client.long_running_recognize(config=config, audio=audio)
op_result = operation.result()
for result in op_result.results:
for alternative in result.alternatives:
print('=' * 20)
print(alternative.transcript)
print(alternative.confidence)
Issue: i got
google.api_core.exceptions.PermissionDenied: 403 my-service-account#my-project.iam.gserviceaccount.com does not have storage.objects.get access to mybucket/audio.mp3.
Full traceback
/home/joo/anaconda3/bin/python /home/joo/Документы/LocalRepository/robotze/speech-to-text-googlecloud.py
Traceback (most recent call last):
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable
return callable_(*args, **kwargs)
File "/home/joo/anaconda3/lib/python3.6/site-packages/grpc/_channel.py", line 565, in __call__
return _end_unary_response_blocking(state, call, False, None)
File "/home/joo/anaconda3/lib/python3.6/site-packages/grpc/_channel.py", line 467, in _end_unary_response_blocking
raise _Rendezvous(state, None, None, deadline)
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with:
status = StatusCode.PERMISSION_DENIED
details = "my-service-account#my-project.iam.gserviceaccount.com does not have storage.objects.get access to mybucket/audio.mp3."
debug_error_string = "{"created":"#1565253582.126380437","description":"Error received from peer ipv4:74.125.131.95:443","file":"src/core/lib/surface/call.cc","file_line":1052,"grpc_message":"my-service-account#my-project.iam.gserviceaccount.com does not have storage.objects.get access to mybucket/audio.mp3.","grpc_status":7}"
>
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/joo/Документы/LocalRepository/robotze/speech-to-text-googlecloud.py", line 46, in <module>
operation = client.long_running_recognize(config=config, audio=audio)
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/cloud/speech_v1/gapic/speech_client.py", line 341, in long_running_recognize
request, retry=retry, timeout=timeout, metadata=metadata
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/api_core/gapic_v1/method.py", line 143, in __call__
return wrapped_func(*args, **kwargs)
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/api_core/retry.py", line 273, in retry_wrapped_func
on_error=on_error,
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/api_core/retry.py", line 182, in retry_target
return target()
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/api_core/timeout.py", line 214, in func_with_timeout
return func(*args, **kwargs)
File "/home/joo/anaconda3/lib/python3.6/site-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable
six.raise_from(exceptions.from_grpc_error(exc), exc)
File "<string>", line 3, in raise_from
google.api_core.exceptions.PermissionDenied: 403 my-service-account#my-project.iam.gserviceaccount.com does not have storage.objects.get access to mybucket/audio.mp3.
Process finished with exit code 1
What i tried: gcloud auth application-default login - login in browser works, but still 403 error
From what i can see on your logs, you are able to authenticate your service account inside your code (you are currently authenticating with: starting-account-*******-239919.iam.gserviceaccount.com), however, that service account doesn't have "storage.objects.get" permission over the object "zaudio/audio.mp3".
So you can either:
A.- Give the proper permissions to that service account (may be the role "storage.objectViewer" inside that bucket would be enough, but you could also set it with the role "storage.admin" so it can have more control over that bucket and others).
B.- Authenticate using other service account that have the proper permissions.
I resolved the following issue:
“google.api_core.exceptions.PermissionDenied: 403 my-service-account#my-project.iam.gserviceaccount.com does not have storage.objects.get access to mybucket/audio.mp3.”
To resolve this issue: go to your bucket, click that three dots, choose “Edit permissions”, Entity set “User”, Name set your email (in this case, my-service-account#my-project.iam.gserviceaccount.com), Access: “Reader”. Save and try again. This should resolve this issue. Regardless whether you have created the bucket, whatnot, you have to do this step to explicitly set permission. Hopefully this is useful.

Python : connection failed after authentication success using PyDrive

I am using python version 3 with PyDrive to connect Google spreadsheet.
I succeeded to open browser and do authentication. However, after that I got an error and program does not continue.
this is an error message
Authentication successful.
Traceback (most recent call last):
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/pydrive/files.py", line 369, in _FilesInsert
http=self.http)
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/googleapiclient/http.py", line 812, in execute
_, body = self.next_chunk(http=http, num_retries=num_retries)
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/oauth2client/_helpers.py", line 133, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/googleapiclient/http.py", line 916, in next_chunk
raise ResumableUploadError(resp, content)
googleapiclient.errors.ResumableUploadError: <HttpError 403 "Project 895099846013 is not found and cannot be used for API calls. If it is recently created, enable Drive API by visiting then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.">
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "drive_control.py", line 10, in <module>
file.Upload()
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/pydrive/files.py", line 285, in Upload
self._FilesInsert(param=param)
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/pydrive/auth.py", line 75, in _decorated
return decoratee(self, *args, **kwargs)
File "/home/PycharmProjects/misc/.venv/lib/python3.5/site-packages/pydrive/files.py", line 371, in _FilesInsert
raise ApiRequestError(error)
pydrive.files.ApiRequestError: <HttpError 403 "Project 895099846013 is not found and cannot be used for API calls. If it is recently created, enable Drive API by visiting url If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.">
this is my code
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
file = drive.CreateFile({'title': 'Hello.txt'})
file.SetContentString('Hello World!')
file.Upload()
this error have clear description in traceback:
403 "Project 895099846013 is not found and cannot be used for API
calls. If it is recently created, enable Drive API by visiting url
In your account, you must have the enabled status of the Google Drive API.
You can see it in the Console Developer toolbar
If you do not see it, follow the instructions

Having trouble trying to use gdata and oauth2 in python

Good evening, i've been trying to migrate my blogger python app to oauth2 since the good old Clientlogin() has been deprecated and erased.
So, basically i searched through the entire web and couldn't manage to make my application to work correctly.
This is the basic code im using for testing:
FLOW = flow_from_clientsecrets('/home/b/client_secret.json',scope='https://www.googleapis.com/auth/blogger',message="Client Secrets Not Found")
storage = Storage('blogger.dat')
credentials = storage.get()
parser = argparse.ArgumentParser(parents=[tools.argparser])
flags = parser.parse_args()
if credentials is None or credentials.invalid:
credentials = run_flow(FLOW, storage, flags)
if credentials.access_token_expired:
credentials.refresh(httplib2.Http())
SCOPE = 'https://www.blogger.com/feeds'
token = gdata.gauth.OAuth2TokenFromCredentials(credentials)
client = gdata.blogger.client.BloggerClient()
token.authorize(client)
post = client.add_post(blog_id, title="blah", body="blah", labels="label", draft=False, title_type="xhtml", body_type="html")
I get a 401 error code, unauthorized everytime i try to do this.
Traceback (most recent call last):
File "/home/b/.eclipse/org.eclipse.platform_4.4.2_1473617060_linux_gtk_x86_64/plugins/org.python.pydev_4.0.0.201504132356/pysrc/pydevd.py", line 2278, in <module>
globals = debugger.run(setup['file'], None, None)
File "/home/b/.eclipse/org.eclipse.platform_4.4.2_1473617060_linux_gtk_x86_64/plugins/org.python.pydev_4.0.0.201504132356/pysrc/pydevd.py", line 1704, in run
pydev_imports.execfile(file, globals, locals) # execute the script
File "/home/b/workspace/BloggerPy/simpleblogger.py", line 53, in <module>
post = client.add_post(blog_id, title="hola", body="holaaa", labels="label", draft=False, title_type="xhtml", body_type="html", token=token)
File "/usr/local/lib/python2.7/dist-packages/gdata/blogger/client.py", line 111, in add_post
return self.post(new_entry, BLOG_POST_URL % blog_id, auth_token=auth_token, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/gdata/client.py", line 690, in post
desired_class=desired_class, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/gdata/client.py", line 298, in request
**kwargs)
File "/usr/local/lib/python2.7/dist-packages/gdata/client.py", line 307, in request
response, Unauthorized)
gdata.client.Unauthorized: Unauthorized - Server responded with: 401, User does not have permission to create new post
Can someone help me out with this? I'd really appreciate it :)
Greetings
Finally i've fixed my issue with gdata.gauth:
I used auth2token = gdata.gauth.OAuth2Token(client_id,client_secret,scope,user_agent)
After getting the authorization token i generate an authorized url to get an access code with auth2token.generate_authorize_url(redirect_uri=URL,approval_prompt="force").
once you get this url, you manually get the code and generate a refresh token, with which you generate an access token:
token = auth2token.get_access_token(code). Easy enough. For any other information as to how to save the token to a blob string in a file here's the reference:
gdata-python-api + Analytics with simple auth

Categories

Resources