Insufficient authentication scopes error using Google Slides API - python

I'm trying to understand how to work with Google Slides API,
I did everything as it was described here.
In "enable Google Slides API" I tried to choose "Desktop app" or "Web Server", but in both ways every time when I try to run quickstart.py file, I get same error:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc?alt=json returned "Request had insufficient authentication scopes.">
This is what i have inside my quickstart.py:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
# The ID of a sample presentation.
PRESENTATION_ID = '1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('slides', 'v1', credentials=creds)
# Call the Slides API
presentation = service.presentations().get(
presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
if __name__ == '__main__':
main()
Updated:
Whole error msg looks like this:
Traceback (most recent call last):
File "/Users/A/PycharmProjects/PyProjects/quickstart.py", line 54, in <module>
main()
File "/Users/A/PycharmProjects/PyProjects/quickstart.py", line 44, in main
presentationId=PRESENTATION_ID).execute()
File "/Users/A/PycharmProjects/PyProjects/venv/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
return wrapped(*args, **kwargs)
File "/Users/A/PycharmProjects/PyProjects/venv/lib/python3.7/site-packages/googleapiclient/http.py", line 907, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/1EAYk18WDjIG-zp_0vLm3CsfQh_i8eXc67Jo2O9C6Vuc?alt=json returned "Request had insufficient authentication scopes.">

Hello I have stumbled upon the same issue it is easily solvable, you just have to approve it manually.
https://developers.google.com/people/quickstart/python#step_1_turn_on_the
So press the Enable the People API button and it should open a new window where you have to login manually first time for the approval hope it helps.

Related

Gmail-API with python

i'm building python GMAIL API for checking emails for 10 email accounts
but in google documentation not very useful.
this seems only support one account
https://github.com/suleenwong/Gmail-API-Python
If we check the default sample python quickstart This sample was designed to be single user but that can be changed.
The following section creates a token.json file when the user authorizes the application. The file will contain the access token and refresh token for the user who authorized the code.
If the file does not exist then the app will prompt the user to authorize it. If it does then the app will load the credentials from that file and run the code with the authorization of that user.
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
To add more users you can simply rename that file tokenUserOne.json, tokenUserTwo.json. Then set it up so that you can supply the file name you want your script to run on. You will only need to authorize each user once. As long as you have a token.json file for each user separated, your app can then be started using which ever token file you want, to access each users data.
https://developers.google.com/gmail/api/quickstart/python -this is the proper documentation everything you need is in here
aka (you also need a client_secet.json file but you will have to get yourself for the google cloud dashbord):
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 googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
def main():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
# Call the Gmail API
service = build('gmail', 'v1', credentials=creds)
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
if not labels:
print('No labels found.')
return
print('Labels:')
for label in labels:
print(label['name'])
except HttpError as error:
# TODO(developer) - Handle errors from gmail API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()

I want to create google sheet from python using Pycharm but its not working

I was try to create google sheet using python in Pycharm but I try very had didn't out bugs.
here I submit my full code and show my error result.
# [START sheets_create]
from __future__ import print_function
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
def create(title):
"""
Creates the Sheet the user has access to.
Load pre-authorized user credentials from the environment.
TODO(developer) - See https://developers.google.com/identity
for guides on implementing OAuth2 for the application.\n"
"""
creds = 'conof.json'
# pylint: disable=maybe-no-member
try:
service = build('sheets', 'v4', credentials=creds)
spreadsheet = {
'properties': {
'title': title
}
}
spreadsheet = service.spreadsheets().create(body=spreadsheet,
fields='spreadsheetId') \
.execute()
print(f"Spreadsheet ID: {(spreadsheet.get('spreadsheetId'))}")
return spreadsheet.get('spreadsheetId')
except HttpError as error:
print(f"An error occurred: {error}")
return error
if __name__ == '__main__':
# Pass: title
create("mysheet1")
# [END sheets_create]
This is default code I found from google sheet development site I just added here my json file from google cloud console generated. I was hard to manage to solve library error's. I am using windows platform.
And my error's
C:\Users\pc\PycharmProjects\createShee\venv\Scripts\python.exe C:/Users/pc/PycharmProjects/createShee/mumu.py
Traceback (most recent call last):
File "C:\Users\pc\PycharmProjects\createShee\mumu.py", line 37, in <module>
create("mysheet1")
File "C:\Users\pc\PycharmProjects\createShee\mumu.py", line 19, in create
service = build('sheets', 'v4', credentials=creds)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\discovery.py", line 298, in build
service = build_from_document(
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\discovery.py", line 604, in build_from_document
http = _auth.authorized_http(credentials)
File "C:\Users\pc\PycharmProjects\createShee\venv\lib\site-packages\googleapiclient\_auth.py", line 124, in authorized_http
return credentials.authorize(build_http())
AttributeError: 'str' object has no attribute 'authorize'
Process finished with exit code 1
Please help me to solve this project.
The credential parameter of build() method can only accept the following objects:
credentials: oauth2client.Credentials or
google.auth.credentials.Credentials, credentials to be used for
authentication.
An easy way to create a credential object is to use the authentication in the Python Quickstart of Google Sheets API.
Just follow the Quickstart guide, change the scope to 'https://www.googleapis.com/auth/spreadsheets' and replace the try-except block with the try-except block in the Create a spreadsheet.
Your code should look like this:
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 googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
def create(title):
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('sheets', 'v4', credentials=creds)
spreadsheet = {
'properties': {
'title': title
}
}
spreadsheet = service.spreadsheets().create(body=spreadsheet,
fields='spreadsheetId') \
.execute()
print(f"Spreadsheet ID: {(spreadsheet.get('spreadsheetId'))}")
return spreadsheet.get('spreadsheetId')
except HttpError as error:
print(f"An error occurred: {error}")
return error
if __name__ == '__main__':
create("mysheet1")
Output:
Notes: Make sure to install the necessary package included in the Quickstart guide, download the credential json file, save it in the same directory as your script and rename it to credentials.json
Reference:
Module discovery
Try replacing creds = 'conof.json' with
credentials = google.oauth2.credentials.Credentials.from_authorized_user_file('conof.json)
and adding the import as necessary.
You are currently passing a string to the credentials parameter in build; however, build expects you to pass a specific type of credentials object to it. You can obtain this credential object from a JSON file using the line of code above. See this answer for more detail.

Retrieve ClassWork from GoogleClassroomApi [403] Python

I am trying to retreive the classwork of each course from Google Classroom API.I have succeeded in getting all the courses, but I am stuck on the course work: <HttpError 403 when requesting https://classroom.googleapis.com/v1/courses/167997334462/courseWork?alt=json returned "Request had insufficient authentication scopes.">.
This is the code I am using:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/classroom.coursework.students.readonly']
def main():
"""Shows basic usage of the Classroom API.
Prints the names of the first 10 courses the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
r"\test\credentials.json", SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('classroom', 'v1', credentials=creds)
# Call the Classroom API
course_work_results = service.courses().courseWork().list(courseId="167997334462").execute()
[...]
if __name__ == '__main__':
main()
I have generated the credidentials using admin account; I've also tried several different Scopes, but same error.
Could you guys please help me here?
I am using Python 3.9.
Thanks,
Alexandru
Since you are using the scope
https://www.googleapis.com/auth/classroom.coursework.students.readonly,
I assume you are a student.
Students are only allowed to access course work of the courses where they are accepted course participants.
Trying to retrieve the course work of another course will result in an 403 error.
If you are not a student, but an Admin of your Google Workspace domain, you should use a wider scope, e.g.
https://www.googleapis.com/auth/classroom.coursework.me.readonly.
Please mind that after changing the scopes in your source code you need to delete your token file to trigger new authentication flow.

Unable to download file by its id from Google Drive

$ pip3 list | grep googl
google-api-python-client 1.7.9
google-auth 1.6.3
google-auth-httplib2 0.0.3
google-auth-oauthlib 0.4.0
I can successfully list files shared to me. But I get "File not found" error when I try to download an existing file by its id. How to download a file by its id?
Script to list files
from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
TOKEN_FILE = 'tockenRead.pickle'
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(TOKEN_FILE):
with open(TOKEN_FILE, 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server()
# Save the credentials for the next run
with open(TOKEN_FILE, 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
q="mimeType != 'application/vnd.google-apps.folder'",
pageSize=10,
fields="nextPageToken, files(id, name)"
).execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
if __name__ == '__main__':
main()
Result
$ python3 list_files.py
Files:
20140810_125633.mp4 (1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE)
Getting started (0B3K2QXOGSOFRc3RhcnRlcl9maWxl)
Script to download file with id 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE
from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.file']
TOKEN_FILE = 'tokenWrite.pickle';
def downloadFile(driveService, fileId):
request = driveService.files().get_media(fileId=fileId)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print ("Download %d%%." % int(status.progress() * 100))
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(TOKEN_FILE):
with open(TOKEN_FILE, 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server()
# Save the credentials for the next run
with open(TOKEN_FILE, 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
if __name__ == '__main__':
main()
Error
$ python3 download_files.py
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=619229308650-91gkhdgo7v0jbt6df1phahmq868eb7gd.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=4mP9kgVJQD4ETOu5JjIRQFBLcyViAG&access_type=offline&code_challenge=ybCzMgZ2SOXdrpZZYn1dq9nSJk8wMtLo7Deg_Xix9So&code_challenge_method=S256
Traceback (most recent call last):
File "download_files.py", line 52, in <module>
main()
File "download_files.py", line 49, in main
downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
File "download_files.py", line 21, in downloadFile
status, done = downloader.next_chunk()
File "/usr/local/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/usr/local/lib/python3.7/site-packages/googleapiclient/http.py", line 705, in next_chunk
raise HttpError(resp, content, uri=self._uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/drive/v3/files/1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE?alt=media returned "File not found: 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE.">
How about this answer?
Reason of issue:
When I saw your scripts, I noticed that the scope of below script are different from the above script. I think that this is the reason of your issue.
At above script, https://www.googleapis.com/auth/drive.metadata.readonly is used. On the other hand, at the below script, https://www.googleapis.com/auth/drive.file is used.
The official document says about the scope of https://www.googleapis.com/auth/drive.file as follows.
View and manage Google Drive files and folders that you have opened or created with this app
This means that when your script uploads a file using the scope of https://www.googleapis.com/auth/drive.file, you can retrieve the file using the scope. But for example, when the file is manually upload to the Google Drive, the file cannot be downloaded by the scope of https://www.googleapis.com/auth/drive.file, even when the file is shared with you.
In order to download the file, how about the following workarounds?
Workaround 1:
You use the scope of https://www.googleapis.com/auth/drive or https://www.googleapis.com/auth/drive.readonly instead of https://www.googleapis.com/auth/drive.file.
Workaround 2:
If you are required to use the scope of https://www.googleapis.com/auth/drive.file, it uploads the file using the scope of https://www.googleapis.com/auth/drive.file. By this, the file can be downloaded by the scope.
Note:
When you change the scopes, please remove the file of tokenWrite.pickle and authorize the scopes again and create new tokenWrite.pickle. By this, you can use new scopes. Please be careful this.
Reference:
Scopes of Drive API, v3
If I misunderstood your question and this was not the direction you want, I apologize.

Google Sheet Api write error

I can't write data to google sheets via python. I did everything like in Google Sheets Api example but it still doesn't work. This is my project:
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools
SCOPES = ['https://www.googleapis.com/auth/spreadsheets','https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file']
SAMPLE_SPREADSHEET_ID = 'ID'
SAMPLE_RANGE = 'Sheet2!A1:A10'
def main():
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('sheets', 'v4', http=creds.authorize(Http()))
values = {'values': [['one','two','three']]}
result = service.spreadsheets().values().append(
spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE,
valueInputOption='RAW',
body=values).execute()
print('{0} cells updated.'.format(result.get('updatedCells')));
if __name__ == '__main__':
main()
And it gives me this errors:
C:\Users\Victor\Anaconda3\python.exe "C:/Users/Victor/Desktop/NEW try/try1.py"
Traceback (most recent call last):
File "C:/Users/Victor/Desktop/NEW try/try1.py", line 31, in <module>
main()
File "C:/Users/Victor/Desktop/NEW try/try1.py", line 27, in main
body=values).execute()
File "C:\Users\Victor\Anaconda3\lib\site-packages\googleapiclient\_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\Victor\Anaconda3\lib\site-packages\googleapiclient\http.py", line 842, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://sheets.googleapis.com/v4/spreadsheets/1RaeZ4QpT3-ZCcIfBDKdtQJt0WDJKiLnBsB3dTC2PoGg/values/Sheet2%21A1%3AA10:append?valueInputOption=RAW&alt=json returned "Request had insufficient authentication scopes.">
Process finished with exit code 1
I pin a screenshot that prooves that i have all the permisions in the api.
Google API
Thank you in advance.
From my understanding, exit code 1 "means there was some issue / problem which caused the program to exit." Trying to debug your code, it seems like your indentation is off. Everything between lines 11 and 25 should have at least one indent so it's considered to be apart of the main() function. Like so:
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file as oauth_file, client, tools
SCOPES = ['https://www.googleapis.com/auth/spreadsheets','https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file']
SAMPLE_SPREADSHEET_ID = 'ID'
SAMPLE_RANGE = 'Sheet2!A1:A10'
def main():
store = oauth_file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('sheets', 'v4', http=creds.authorize(Http()))
values = {'values': [['one','two','three']]}
result = service.spreadsheets().values().append(
spreadsheetId=SAMPLE_SPREADSHEET_ID, range=SAMPLE_RANGE,
valueInputOption='RAW',
body=values).execute()
print('{0} cells updated.'.format(result.get('updatedCells')));
if __name__ == '__main__':
main()
Also, the Google Sheets API Quick Start for Python gets updated frequently, so I would try using the new code featured here. Let us know what happens after you fix the indentation or you decide to go with Google's updated code.

Categories