> This page is for プラットフォーム, version レガシー.
> For other versions, use one of these documentation indexes:
> - V4 (default): https://developer.frame.io/platform/v4/llms.txt
> - V4 Experimental: https://developer.frame.io/platform/v4-experimental/llms.txt
> - レガシー: https://developer.frame.io/platform/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.frame.io/_mcp/server.

# OAuth 2 トークンの更新

<Warning title="このガイドは、OAuth 2 アプリが構築済みであることを前提としています">
まだの場合は、[こちら](/oauth-2-applications/building-an-oauth-2-app)のガイドを参照してください。OAuth 2 資格情報の付与が成功して `access_token` と `refresh_token` を取得したら、ここに戻ってきてください。
</Warning>

## トークン更新の基本
OAuth2.0 資格情報リクエストにオフラインスコープを含めた場合、Frame.io の Accounts アプリケーションを介した認証に成功すると、次のようなペイロードが返されます。 ******

```json
{
  "access_token":"BEARER_TOKEN",
  "expires_in":3600,
  "refresh_token":"REFRESH_TOKEN",
  "scope":"account.read offline",
  "token_type":"bearer"
}
```

`access_token` は、認証されたユーザーの代理で動作するために使用できるベアラートークンであり、3600 秒（1 時間）後に期限切れになります。その後、`refresh_token` を使用して新しい `access_token` を取得できます。更新トークンは 30 日後に期限切れになります。その時点で、ユーザーに一からログインしてもらうことが必要になり、新しいアクセス／更新トークンペアなどが生成されます。

オフラインスコープを明示的にリクエストしなかった場合は、`refresh_token` **を受け取らないので、1 時間後にユーザーを完全に再認証する必要があります。

### 認証に成功したときの更新トークンのキャプチャ
言うまでもなく、持っていない `refresh_token` を使用することはできません。アプリで次のようにしてください。
* **オフライン**スコープをリクエストする
* 正常なコールバックで返された `refresh_token` をキャプチャする

便宜上、[OAuth 2 アプリガイド](/oauth-2-applications/building-an-oauth-2-app)からのコールバックがここに再現されており、`os` 更新トークンを隠す呼び出しがあります。次の 2 つの例が提供されていることに注意してください。1 つは PKCE が設定されている例（基本認証ヘッダーを含まない）、もう 1 つは設定されていない例（基本認証ヘッダーを含む）。

### PKCE なし

**`Python`**

```python title="Python"
def callback():
  # Where `request` refers to our initial call to the auth URL
  state = request.args.get('state')
  scope = request.args.get('scope')
  code = request.args.get('code')
  error = request.args.get('error')

  if error:
    return "Error: " + error

  # Set up for client authorization and set up the data you need to send.
  client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID, CLIENT_SECRET)

  post_data = {
    "grant_type": "authorization_code",
    "code": code,
    "redirect_uri": REDIRECT_URI,
    "state": state,
    "scope": SCOPE
  }

  # Send a POST request with the data you need to receive an access token. 
  response = requests.post(TOKEN, auth=client_auth, data=post_data)    
	# Stash the refresh token for later
  os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]

  return response.text
```

### PKCE を使用

**`Python`**

```python title="Python"
def callback():
  # Where `request` refers to our initial call to the auth URL
  state = request.args.get('state')
  scope = request.args.get('scope')
  code = request.args.get('code')
  error = request.args.get('error')

  if error:
    return "Error: " + error

  # If using PKCE, you must include the CLIENT_ID in your request body  
  post_data = {
    "grant_type": "authorization_code",
    "code": code,
    "redirect_uri": REDIRECT_URI,
    "state": state,
    "scope": SCOPE
    "client_id": CLIENT_ID 
  }

  # Send a POST request with the data you need to receive an access token.
  # If using PKCE, use the below request with no auth
  response = requests.post(TOKEN_URL, data=post_data)
  # Stash the refresh token for later
  os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]

  return response.text
```
## 更新の実行
更新自体は、Frame.io のトークン URL への 1 回の呼び出しです。
* メソッド：POST
* URL：**https://applications.frame.io/oauth2/token**
* `Content-Type`：application/x-www-form-urlencoded **

更新には常に、フォームデータに少なくとも次の 3 つの属性が含まれます。
* `grant_type`：refresh_token **
* `scope`：\<SCOPES>
* `refresh_token`：\<REFRESH_TOKEN>

PKCE を使用している場合は、このフォームデータにアプリの `client_id` を含めることが必要になります。そうでない場合は、アプリの `client_id` および `client_secret` をそれぞれユーザー名、パスワードとして含んだ基本認証ヘッダーを含めることが必要になります。
### PKCE なし
PKCE なしで[初期認証コールバックを行う](/oauth-2-applications/building-an-oauth-2-app#the-callback)場合と同様に、この標準更新には、基本認証ヘッダーで `client_id`および `client_secret` をユーザー名およびパスワードとして指定する必要があります。

**`Python`**

```python title="Python"
def refresh():
  # Fetch the refresh token, assuming we have it
  REFRESH_TOKEN = os.environ.get('REFRESH_TOKEN')

  client_auth = requests.auth.HTTPBasicAuth(CLIENT_ID,CLIENT_SECRET)
  post_data = {
    "grant_type": "refresh_token",
    "scope": SCOPE,
    "refresh_token": REFRESH_TOKEN
    # if using PKCE, you will need to include your client_id as below
    # "client_id": CLIENT_ID 
  }

  response = requests.post(TOKEN_URL, auth=client_auth, data=post_data)
  # Catch + stash a new Refresh Token
  os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]

  return response.text
```
### PKCE を使用
繰り返しますが、初期 `/callback` サイクルのルールを模倣しています。
* `Authorization` ヘッダーは含めません
* ペイロードに `client_id` を含める必要があります

**`Python`**

```python title="Python"
def refresh():
  # Fetch the refresh token, assuming we have it
  REFRESH_TOKEN = os.environ.get('REFRESH_TOKEN')

  post_data = {
    "grant_type": "refresh_token",
    "scope": SCOPE,
    "refresh_token": REFRESH_TOKEN
    "client_id": CLIENT_ID 
  }

  response = requests.post(TOKEN_URL, data=post_data)
  # Catch + stash a new Refresh Token
  os.environ['REFRESH_TOKEN'] = response.json()["refresh_token"]

  return response.text
```
完了しました。OAuth2.0 クライアントアプリケーションのトークンライフサイクル全体を処理できるようになりました。