在Python中在无界面机器上授权Google API

huangapple go评论62阅读模式
英文:

Authorizing Google API on Headless Machine in Python

问题

在树莓派4上运行Linux(使用Raspberry OS上的Docker中的Ubuntu和Python)。

遵循Google的Python快速入门指南,并将其进行到要求我转到此类URL的程度:
请访问此URL以授权此应用程序: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=xxxxx&redirect_uri=http%3A%2F%2Flocalhost%3A59875%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&state=xxxxx&access_type=offline

由于我是无头的并且在SSH上,我将其复制到我的GUI计算机上并进行签名授权,但我得到了一个重定向到localhost:59875/?state=xxxxx&code=xxxxx&scope=xxxx的请求,这显然不会打开,因为我本地机器上没有任何内容在监听。我在上面的链接中看到了带有localhost的重定向URI,但更改它是无效的,根据这个

如何在无头机器上授权Google API?

除了在我的树莓派上创建一个网页并使用它来运行Python(这超出了我现在想做的范围,尤其是不知道它是否能正常工作),我该怎么办?

编辑
我正在创建一个将与Google日历交互的Python程序。我有一个开发者帐户和凭据,以及个人帐户和凭据。我试图在开发者凭据下创建此功能,然后允许(长期)用户进行身份验证。因此,测试用户。

英文:

Running Linux (ubuntu and python in docker on Raspberry OS) on a headless Raspberry Pi 4.

Followed Google's Python Quickstart Guide and got it to the point where it asks me to go to a URL like this:

Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=xxxxx&redirect_uri=http%3A%2F%2Flocalhost%3A59875%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&state=xxxxx&access_type=offline

Because I am headless and on SSH, I copied to my GUI computer and sign in authorize, but I get a request back to localhost:59875/?state=xxxxx&code=xxxxx&scope=xxxx which obviously does not open as nothing on my local machine is listening. I see that redirect URI in the above link with localhost, but changing that is invalid per this.

How can I authorize Google API on a headless machine?

Short of creating a webpage on my pi and using that to run the python (which is more than I want to do right now, especially not knowing if it will work), how can I do this?

EDIT
I am creating a python program that will interact with Google Calendar. I have a developer account and credentials, and a personal account and credentials. I am trying to create this under the developer credentials and then enable (long term) users to authenticate themselves. Hence the test users.

答案1

得分: 2

为了在成功进行Google OAuth2授权后避免重定向,并且手动将授权码粘贴到脚本中,您可以使用OAuth2规范中定义的特殊值urn:ietf:wg:oauth:2.0:oob

日历快速入门代码进行修改,可以像这样使用:

...
# 如果没有(有效的)凭据可用,请让用户登录。
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,
            redirect_uri='urn:ietf:wg:oauth:2.0:oob')

        auth_uri, _ = flow.authorization_url()
        print(f'请在您的本地计算机上访问 {auth_uri}')

        # 用户将获得授权码。此代码用于获取访问令牌。
        code = input('输入授权码: ')
        flow.fetch_token(code=code)

        creds = flow.credentials
    # 保存凭据以供下次运行使用
    with open('token.json', 'w') as token:
        token.write(creds.to_json())
...

注意 这有多种实现方式:您可以创建一个服务帐户供应用程序使用,并与服务帐户用户共享您的日历。然后,您可以通过使用calendarId参数访问最终用户的日历。

您应该查阅Google API文档,了解哪种方式最适合您。

英文:

To avoid redirection after successful Google OAuth2 authorization, and instead fetch the authorization code that you manually paste into the script you can use the special value urn:ietf:wg:oauth:2.0:oob defined by the OAuth2 specification.

Taking the calendar quickstart code and modifying it, it can be used something like this:

...
# 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,
                redirect_uri='urn:ietf:wg:oauth:2.0:oob')

            auth_uri, _ = flow.authorization_url()
            print(f'Please visit {auth_uri} on your local computer')

            # The user will get an authorization code. This code is used to get the
            # access token.
            code = input('Enter the authorization code: ')
            flow.fetch_token(code=code)

            creds = flow.credentials
        # Save the credentials for the next run
        with open('token.json', 'w') as token:
            token.write(creds.to_json())
...

Note There is more than one way to achieve this: you can create a service account to be used by the app, and share your calendar with the service app user. You would then access the end user's calendar by using the calendarId param.

You should explore the Google API documentation and see what fits you the best.

huangapple
  • 本文由 发表于 2023年5月15日 05:47:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76249814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定