刷新 OAuth 2 令牌

本指南假定您已经构建了一个 OAuth2 应用程序

如果尚未构建,请参阅指南,并在从成功的 OAuth 2 凭据授权中捕获 access_tokenrefresh_token 之后再返回此处。

令牌刷新基础知识

假设您在 OAuth2.0 凭据请求中包含了 offline 权限范围,那么通过 Frame.io 的帐户应用程序成功完成验证身份后将返回一个如下所示的负载:

1{
2 "access_token":"BEARER_TOKEN",
3 "expires_in":3600,
4 "refresh_token":"REFRESH_TOKEN",
5 "scope":"account.read offline",
6 "token_type":"bearer"
7}

access_token 是一个持有者令牌,可用于代表经过身份验证的用户执行操作;它将在 3600 秒(一小时)后过期;在此之后,可以使用 refresh_token 来获取新的 access_token。刷新令牌随后将在 30 天后过期,届时您需要让用户重新登录,生成一对新的访问/刷新令牌;如此循环。如果您未明确请求 offline 权限范围,则不会收到 refresh_token,因此一小时后您将需要让用户完全重新进行身份验证。

成功完成身份验证时捕获刷新令牌

不言而喻,您无法使用您没有的 refresh_token,因此请确保在您的应用程序中:

  • 请求 offline 权限范围
  • 捕获成功回调中返回的 refresh_token

为方便起见,此处重现了我们 OAuth 2 应用程序指南中的回调,其中包含一个用于存储刷新令牌的 os 调用。请注意,下面提供了两个示例:一个配置了 PKCE(不包括基本身份验证标头),另一个未配置(包括基本身份验证标头)。

不使用 PKCE

Python
1def callback():
2 # Where `request` refers to our initial call to the auth URL
3 state = request.args.get('state')
4 scope = request.args.get('scope')
5 code = request.args.get('code')
6 error = request.args.get('error')
7
8 if error:
9 return "Error: " + error
10
11 # Set up for client authorization and set up the data you need to send.
12 client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)
13
14 post_data = {
15 "grant_type": "authorization_code",
16 "code": code,
17 "redirect_uri": REDIRECT_URI,
18 "state": state,
19 "scope": SCOPE
20 }
21
22 # Send a POST request with the data you need to receive an access token.
23 response = requests.post(TOKEN, auth=client_auth, data=post_data)
24 # Stash the refresh token for later
25 os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]
26
27 return response.text

使用 PKCE

Python
1def callback():
2 # Where `request` refers to our initial call to the auth URL
3 state = request.args.get('state')
4 scope = request.args.get('scope')
5 code = request.args.get('code')
6 error = request.args.get('error')
7
8 if error:
9 return "Error: " + error
10
11 # If using PKCE, you must include the CLIENT_ID in your request body
12 post_data = {
13 "grant_type": "authorization_code",
14 "code": code,
15 "redirect_uri": REDIRECT_URI,
16 "state": state,
17 "scope": SCOPE
18 "client_id": CLIENT_ID
19 }
20
21 # Send a POST request with the data you need to receive an access token.
22 # If using PKCE, use the below request with no auth
23 response = requests.post(TOKEN_URL, data=post_data)
24 # Stash the refresh token for later
25 os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]
26
27 return response.text

执行刷新

刷新本身是对 Frame.io 令牌 URL 的一次单一调用:

一次刷新在其表单数据中始终至少包含以下三个属性:

  • grant_typerefresh_token
  • scope:<scopes>
  • refresh_token:<refresh_token>

如果您使用的是 PKCE,则需要在此表单数据中包含应用程序的 client_id;如果不使用,则需要包含一个基本身份验证标头,并分别以应用程序的 client_idclient_secret 作为用户名和密码。

不使用 PKCE

与不使用 PKCE 时进行初始身份验证回调类似,此标准刷新需要在基本身份验证标头中提供 client_idclient_secret,分别作为用户名和密码。

Python
1def refresh():
2 # Fetch the refresh token, assuming we have it
3 REFRESH_TOKEN = os.environ.get('REFRESH_TOKEN')
4
5 client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID,CLIENT_SECRET)
6 post_data = {
7 "grant_type": "refresh_token",
8 "scope": SCOPE,
9 "refresh_token": REFRESH_TOKEN
10 # if using PKCE, you will need to include your client_id as below
11 # "client_id": CLIENT_ID
12 }
13
14 response = requests.post(TOKEN_URL, auth=client_auth, data=post_data)
15 # Catch + stash a new Refresh Token
16 os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]
17
18 return response.text

使用 PKCE

同样,我们遵循初始 /callback 循环的规则:

  • 我们不包含 Authorization 标头
  • 我们必须在负载中包含 client_id
Python
1def refresh():
2 # Fetch the refresh token, assuming we have it
3 REFRESH_TOKEN = os.environ.get('REFRESH_TOKEN')
4
5 post_data = {
6 "grant_type": "refresh_token",
7 "scope": SCOPE,
8 "refresh_token": REFRESH_TOKEN
9 "client_id": CLIENT_ID
10 }
11
12 response = requests.post(TOKEN_URL, data=post_data)
13 # Catch + stash a new Refresh Token
14 os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]
15
16 return response.text

祝贺您!现在,您可以处理 OAuth2.0 客户端应用程序的整个令牌生命周期了。