Google Calendar API v3 - 如何获取刷新令牌 (Python)

发布于 2024-12-21 20:19:36 字数 1992 浏览 0 评论 0原文

我正在尝试编写一个 Django 应用程序,它在特定的 Google 日历中创建事件。到目前为止我已经成功了。只有一个小问题:

我不知道如何使用 google python 客户端获取刷新令牌。

结果是,在我的令牌过期后,应用程序无法运行,我必须创建一个新令牌。如果我对文档的理解正确,那就是刷新令牌的用武之地。

访问令牌的生命周期有限,在某些情况下,应用程序需要在单个访问令牌的生命周期之外访问 Google API。在这种情况下,您的应用程序可以获得所谓的刷新令牌。刷新令牌允许您的应用程序获取新的访问令牌。

Google 文档(请参阅“基本步骤”,第 4 节)

我的代码

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

FLOW = OAuth2WebServerFlow(
    client_id=GOOGLE_API_CLIENT_ID,
    client_secret=GOOGLE_API_CLIENT_SECRET,
    scope=GOOGLE_API_CALENDAR_SCOPE,
    user_agent=GOOGLE_API_USER_AGENT)

storage = Storage(GOOGLE_API_CREDENTIAL_PATH)
credentials = storage.get()
if credentials is None or credentials.invalid == True:
  credentials = run(FLOW, storage)

http = httplib2.Http()
http = credentials.authorize(http)

service = build(serviceName='calendar', version='v3', http=http,
   developerKey=GOOGLE_API_DEVELOPER_KEY)

event = {
    [... Dictionary with all the necessary data here ...]
}

created_event = service.events().insert(calendarId=GOOGLE_API_CALENDAR_ID, body=event).execute()

这就是示例来自谷歌文档。有趣的是存储。它是保存一些凭据数据的文件。

我的存储文件的内容:

{
    "_module": "oauth2client.client", 
    "_class": "OAuth2Credentials", 
    "access_token": [redacted], 
    "token_uri": "https://accounts.google.com/o/oauth2/token", 
    "invalid": true, 
    "client_id": [redacted], 
    "client_secret": [redacted], 
    "token_expiry": "2011-12-17T16:44:15Z", 
    "refresh_token": null, 
    "user_agent": [redacted]
}

其中应该有一个刷新令牌,但它是null。所以我想我可以以某种方式请求刷新令牌。

我将不胜感激任何有关如何使其发挥作用的帮助。如果您需要更多信息,请告诉我。

I am trying to write a Django app which creates events in a specific Google calendar. So far I have been successful. There is only a little problem:

I don't know how to obtain a refresh token with the google python client.

The result is that after my token expires the app does not work and I have to create a new token. If I understand the documentation correct that's where the refresh token comes in.

Access tokens have a limited lifetime and, in some cases, an application needs access to a Google API beyond the lifetime of a single access token. When this is the case, your application can obtain what is called a refresh token. A refresh token allows your application to obtain new access tokens.

Google Documentation (see "Basic Steps", Section 4)

My code

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

FLOW = OAuth2WebServerFlow(
    client_id=GOOGLE_API_CLIENT_ID,
    client_secret=GOOGLE_API_CLIENT_SECRET,
    scope=GOOGLE_API_CALENDAR_SCOPE,
    user_agent=GOOGLE_API_USER_AGENT)

storage = Storage(GOOGLE_API_CREDENTIAL_PATH)
credentials = storage.get()
if credentials is None or credentials.invalid == True:
  credentials = run(FLOW, storage)

http = httplib2.Http()
http = credentials.authorize(http)

service = build(serviceName='calendar', version='v3', http=http,
   developerKey=GOOGLE_API_DEVELOPER_KEY)

event = {
    [... Dictionary with all the necessary data here ...]
}

created_event = service.events().insert(calendarId=GOOGLE_API_CALENDAR_ID, body=event).execute()

This is pretty much the example from the Google documentation. The interesting bit is the Storage. It's a file where some credential data is saved.

Content of my storage file:

{
    "_module": "oauth2client.client", 
    "_class": "OAuth2Credentials", 
    "access_token": [redacted], 
    "token_uri": "https://accounts.google.com/o/oauth2/token", 
    "invalid": true, 
    "client_id": [redacted], 
    "client_secret": [redacted], 
    "token_expiry": "2011-12-17T16:44:15Z", 
    "refresh_token": null, 
    "user_agent": [redacted]
}

There should be a refresh token in there, but instead it's null. So I figure I can somehow request a refresh token.

I would appreciate any help on how I can get this to work. If you need more information, please tell me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

三生殊途 2024-12-28 20:19:36

我不知道如何使用 Python 客户端或日历 API 执行此操作(我只是使用 ruby​​ OAuth2 库来访问联系人 API),但我发现我需要向用户请求“离线”访问。

这是通过将值为“offline”的“access_type”参数添加到授权 URL(将用户重定向到单击“我希望允许此应用程序获取我的数据”的 URL)来完成的。

如果您这样做,当您向 google 请求访问令牌时,您会在 JSON 响应中获得一个刷新令牌。否则,您只能获得访问令牌(有效期为一小时)。

这个要求显然是最近添加的(并且可能没有很好的记录)。

您过去无需获得特定的“离线”权限即可获得刷新令牌。

希望这能为您指明正确的方向。

I don't know how to do this with the Python Client or the Calendar API (I'm just using a ruby OAuth2 library for access to the Contacts API), but I found I needed to request "offline" access from the user.

This is done by adding the an "access_type" parameter with the value "offline" to the authorization url (the one you redirect the user to to click "I want to allow this application to get at my data").

If you do this, you get a refresh_token back in your JSON response when you ask google for access tokens. Otherwise you only get the access token (which is valid for an hour).

This requirement was apparently added recently (and may not be wonderfully documented).

You used to get a refresh token without having to get specific "offline" permission.

Hope this points you in the right direction.

还如梦归 2024-12-28 20:19:36

因此,如果您在未设置 access_type='offline' 的情况下已接受同意,则需要通过传递 approval_prompt='force' 来强制用户同意您的应用的离线访问权限代码>.

self.flow = OAuth2WebServerFlow(
    client_id=self.client_id,
    client_secret=self.client_secret,
    scope=self.SCOPE,
    user_agent=user_agent,
    redirect_uri='urn:ietf:wg:oauth:2.0:oob',
    access_type='offline', # This is the default
    approval_prompt='force'
)

然后,您可以在获取刷新令牌后删除强制提示/将其设置为auto

So if you've already accepted consent without setting access_type='offline', you need to force the user to consent to your app with offline access by also passing approval_prompt='force'.

self.flow = OAuth2WebServerFlow(
    client_id=self.client_id,
    client_secret=self.client_secret,
    scope=self.SCOPE,
    user_agent=user_agent,
    redirect_uri='urn:ietf:wg:oauth:2.0:oob',
    access_type='offline', # This is the default
    approval_prompt='force'
)

Then you can remove the force prompt/set it to auto after you get the refresh token.

雪化雨蝶 2024-12-28 20:19:36

2017-06-16 起,答案似乎已被弃用。

  • approval_prompt 已弃用
  • prompt=force 无效

以下是一个有效示例:

from oauth2client.client import OAuth2WebServerFlow

flow = OAuth2WebServerFlow(
    client_id=CLIEN_ID,
    client_secret=CLIENT_SECRET,
    scope=SCOPES,
    redirect_uri='http://localhost/gdrive_auth',
    access_type='offline',
    prompt='consent',
)

print(flow.step1_get_authorize_url())

The answers seems to be deprecated as of 2017-06-16.

  • approval_prompt is deprecated
  • prompt=force is not valid

Here is a working example:

from oauth2client.client import OAuth2WebServerFlow

flow = OAuth2WebServerFlow(
    client_id=CLIEN_ID,
    client_secret=CLIENT_SECRET,
    scope=SCOPES,
    redirect_uri='http://localhost/gdrive_auth',
    access_type='offline',
    prompt='consent',
)

print(flow.step1_get_authorize_url())
治碍 2024-12-28 20:19:36

如果您遵循本手册https://developers.google.com/identity/protocols/OAuth2WebServer并且您无法接收refresh_token,请尝试在此处添加prompt='consent'

authorization_url, state = flow.authorization_url(
    # Enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    prompt='consent',
    # Enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true')

这里描述了为什么它可以发生

If you follow this manual https://developers.google.com/identity/protocols/OAuth2WebServer and you can not receive refresh_token, try to add prompt='consent' here:

authorization_url, state = flow.authorization_url(
    # Enable offline access so that you can refresh an access token without
    # re-prompting the user for permission. Recommended for web server apps.
    access_type='offline',
    prompt='consent',
    # Enable incremental authorization. Recommended as a best practice.
    include_granted_scopes='true')

Here is described why it can happen

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文