> This page is for 플랫폼, version 레거시.
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - V4 실험적: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - 레거시: https://next.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://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.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>


## 토큰 새로 고침의 기본

OAuth 2.0 자격 증명 요청에 ***offline*** 권한을 포함했다고 가정할 때, 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일 후에 만료되며, 이 시점이 되면 사용자가 처음부터 다시 로그인하여 새로운 액세스/새로 고침 토큰 쌍을 생성해야 합니다. *offline* 권한을 명시적으로 요청하지 않으면 `refresh_token`을 수신할 수 없으므로, 1시간 후에 사용자를 완전히 재인증해야 합니다.

### 인증 성공 시 새로 고침 토큰 캡처하기

당연한 이야기지만, 보유하지 않은 `refresh_token`은 사용할 수 없으므로 앱에서 다음 사항을 반드시 확인하세요.
* **offline** 권한 요청
* 성공적인 콜백에서 반환된 `refresh_token` 캡처

편의를 위해 [OAuth 2 앱 가이드](/oauth-2-applications/building-an-oauth-2-app)의 콜백을 새로 고침 토큰을 보관하기 위한 `os` 호출과 함께 아래에 재현해 두었습니다. PKCE가 구성된 예시(기본 인증 헤더 미포함)와 구성되지 않은 예시(기본 인증 헤더 포함)의 두 가지 예시가 제공된다는 점에 유의하세요.

### 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에 대한 단일 호출입니다.



* 메서드: POST
* URL: **https://applications.frame.io/oauth2/token**
* `Content-Type`: *application/x-www-form-urlencoded*




새로 고침 시 양식 데이터에 항상 최소한 다음 세 가지 속성이 포함됩니다.



* `grant_type`: *refresh_token*
* `scope`: &lt;scopes&gt;
* `refresh_token`: &lt;refresh_token&gt;

PKCE를 사용 중인 경우 이 양식 데이터에 앱의 `client_id`를 포함해야 합니다. 사용하지 않는 경우, Basic Authentication 헤더를 포함하고 앱의 `client_id`와 `client_secret`을 각각 Username과 Password로 지정해야 합니다.

### PKCE 미사용

PKCE 없이 [초기 인증 콜백을 수행하는 것](/oauth-2-applications/building-an-oauth-2-app#the-callback)과 유사하게, 이 표준 새로 고침 작업도 Basic Authentication 헤더의 Username과 Password에 `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
```




축하합니다!이제 OAuth 2.0 클라이언트 애플리케이션의 전체 토큰 수명 주기를 처리할 수 있습니다.