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

18 投票
4 回答
10625 浏览
提问于 2025-04-17 08:33

我正在尝试写一个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()

这基本上是Google文档中的示例。比较有意思的是存储部分。它是一个文件,用来保存一些凭证数据。

我的存储文件内容:

{
    "_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。所以我想我可以以某种方式请求一个刷新令牌

如果有人能帮我解决这个问题,我将非常感激。如果你需要更多信息,请告诉我。

4 个回答

5

这个答案似乎在2017年6月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())
14

所以,如果你已经让用户同意使用你的应用,但没有设置 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

19

我不知道怎么用Python客户端或者日历API来做这个(我只是用一个Ruby的OAuth2库来访问联系人API),但我发现我需要向用户请求“离线”访问权限。

这可以通过在授权网址中添加一个“access_type”参数,并把它的值设为“offline”来实现(这个网址是你引导用户点击“我想允许这个应用访问我的数据”的地方)。

如果你这样做,当你向谷歌请求访问令牌时,你会在JSON响应中得到一个refresh_token。否则你只会得到一个访问令牌(这个令牌的有效期是一个小时)。

这个要求显然是最近才添加的(可能文档上没有很好地说明)。

以前你可以在不需要特别请求“离线”权限的情况下就得到一个refresh token。

希望这能给你指明方向。

撰写回答