我想将以下代码从oauth2client升级到google-auth。是的,这段代码确实有效,是他们网站上 Google 演示的复制粘贴。
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# If modifying these scopes, delete the file token.json.
SCOPES = 'https://www.googleapis.com/auth/presentations.readonly'
# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
# 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.
# delete the file to for authentication and authorization again
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
# credentials.json is issued by Google for the application
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('slides', 'v1', http=creds.authorize(Http()))
# 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()
我能够升级大部分(我认为),但找不到tools.run_flow
使用google-auth的等价物。下面是我的升级版,除了机制之外,它拥有一切(我认为)tools.run_flow
。如何tools.run_flow
使用google-auth完成?
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
PRESENTATION_ID = '<some id>'
credentials = service_account.Credentials.from_service_account_file(
"the-json-file.json",
scopes=SCOPES
)
service = build('slides', 'v1', credentials=credentials)
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'))))
当我使用google-auth方法运行上述代码时,我得到以下结果:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/<some id>?alt=json returned "The caller does not have permission">
附加上下文,我正在尝试构建一个 Python 脚本来访问 Google 幻灯片以对幻灯片内容执行一些处理。我只是在阅读,而不是在写 Google 幻灯片。上面的代码是我尝试为我的 GSuite 帐户(我是我的组织的 GSuite 的管理员)处理访问 Google 幻灯片内容的身份验证和授权部分。使用旧oauth2client的第一个示例效果很好,但是由于不推荐使用oauth2client并且建议使用google-auth,因此我想使用最新的库以“正确”的方式进行操作。
更新
我用以下代码解决了部分问题:
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
import os
import json
def get_credentials():
CLIENT_SECRET_FILE = '<some file>'
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
credentials_path = '<some path>/token.json'
if os.path.exists(credentials_path):
# expect these to be valid. may expire at some point, but should be refreshed by google api client...
return Credentials.from_authorized_user_file(credentials_path, scopes=SCOPES)
else:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE,
scopes=SCOPES,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
auth_url, _ = flow.authorization_url(prompt='consent')
print('Please go to this URL and finish the authentication flow: {}'.format(auth_url))
code = input('Enter the authorization code: ')
flow.fetch_token(code=code)
credentials = flow.credentials
credentials_as_dict = {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'id_token': credentials.id_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret
}
with open(credentials_path, 'w') as file:
file.write(json.dumps(credentials_as_dict))
return credentials
# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'
service = build('slides', 'v1', credentials=get_credentials())
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'))))
我现在的挑战是让网络浏览器自动打开。我可以复制并粘贴链接并手动获取代码,一切正常。理想情况下,我希望像在旧库中那样自动打开 Web 浏览器并捕获令牌。
解决了
将前面代码示例中的部分代码更新为:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE,
scopes=SCOPES,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
credentials = flow.run_local_server()
credentials_as_dict = {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'id_token': credentials.id_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret
}
Web 浏览器会自动打开并捕获令牌值。一切都很好。