> ## Documentation Index
> Fetch the complete documentation index at: https://generaltranslation.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth 2.0 Authorization Code Flow와 PKCE를 사용해 엔드포인트에 연결하는 방법

<div id="how-to-connect-to-endpoints-using-oauth-20-authorization-code-flow-with-pkce">
  ### PKCE를 사용하는 OAuth 2.0 승인 코드 플로우로 엔드포인트에 연결하는 방법
</div>

<div id="how-to-connect-to-the-endpoints">
  #### 엔드포인트에 연결하는 방법
</div>

사용자를 인증하려면 App에서 인가 플로우를 구현해야 합니다. 이 인가 플로우를 통해 사용자를 X의 인가 대화상자로 보낼 수 있습니다. 그 이후부터는 기본 X 사용 환경에서 인가 대화상자를 표시하고 App을 대신해 인가 과정을 처리합니다. 사용자는 App에 권한을 부여하거나 권한 부여를 거부할 수 있습니다. 사용자가 선택을 완료하면 X는 사용자를 App으로 리디렉션하고, 그곳에서 (사용자가 App을 인가한 경우) 인가 코드를 액세스 토큰으로 교환하거나 (사용자가 App을 인가하지 않은 경우) 거부 상황을 처리할 수 있습니다.

<div id="working-with-confidential-clients">
  #### 기밀 클라이언트 사용하기
</div>

기밀 클라이언트를 사용하는 경우, 토큰 엔드포인트에 요청을 보낼 때 [기본 인증](https://datatracker.ietf.org/doc/html/rfc2617#section-2) 방식을 사용해 base64로 인코딩한 Authorization 헤더를 생성해야 합니다.

자격 증명에서 `userid`와 `password`는 base64로 인코딩된 문자열 안에서 콜론(":") 문자 하나로 구분됩니다.

예시는 다음과 같습니다:

`-header 'Authorization: Basic V1ROclFTMTRiVWhwTWw4M2FVNWFkVGQyTldNNk1UcGphUTotUm9LeDN4NThKQThTbTlKSXQyZm1BanEzcTVHWC1icVozdmpKeFNlR3NkbUd0WEViUA=='`

사용자 에이전트가 Client ID "Aladdin"과 password "open sesame"를 전송하려는 경우, 다음과 같은 헤더 필드를 사용합니다:

`Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==`

기본 인증 헤더를 생성하려면, App의 “Keys and Tokens” 페이지( [개발자 콘솔](https://developer.x.com/en/portal/dashboard) 내에 위치)에서 확인할 수 있는 Client ID와 Client Secret에 base64 인코딩을 적용해야 합니다.

<div id="steps-to-connect-using-oauth-20">
  #### OAuth 2.0을 사용하여 연결하는 단계
</div>

**1단계: Authorize URL 구성하기**

App은 필요한 scope를 지정하여 X로 향하는 authorize URL을 구성해야 합니다. 예를 들어, App이 Tweet과 사용자 조회, 팔로우 관리를 해야 한다면 다음 scope를 요청해야 합니다:

`tweet.read%20users.read%20follows.read%20follows.write`

이 URL에는 다른 필수 매개변수 외에 `code_challenge`와 state 매개변수도 포함됩니다. 운영 환경에서는 `code_challenge`에 임의의 문자열을 사용해야 합니다.

**2단계: GET oauth2/authorize**

사용자가 인증을 완료하고 애플리케이션에 authorization code를 보내도록 해야 합니다. App에 대해 OAuth 2.0을 활성화한 경우, App의 “Keys and Tokens” 페이지에서 Client ID를 확인할 수 있습니다.

사용자를 리디렉션할 예시 URL은 다음과 같습니다:

```
https://x.com/i/oauth2/authorize?response_type=code&client_id=M1M5R3BMVy13QmpScXkzTUt5OE46MTpjaQ&redirect_uri=https://www.example.com&scope=tweet.read%20users.read%20follows.read%20follows.write&state=state&code_challenge=challenge&code_challenge_method=plain
```

offline\_access가 포함된 URL의 예시는 다음과 같습니다:

```
https://x.com/i/oauth2/authorize?response_type=code&client_id=M1M5R3BMVy13QmpScXkzTUt5OE46MTpjaQ&redirect_uri=https://www.example.com&scope=tweet.read%20users.read%20follows.read%20offline.access&state=state&code_challenge=challenge&code_challenge_method=plain
```

인증이 성공하면 `redirect_uri` 로 `auth_code` 파라미터가 포함된 요청이 전달됩니다. 이때 애플리케이션은 `state` 파라미터를 검증해야 합니다.

`Client`의 `redirect_uri` 로 전달되는 요청 예시는 다음과 같습니다:

```
https://www.example.com/?state=state&code=VGNibzFWSWREZm01bjN1N3dicWlNUG1oa2xRRVNNdmVHelJGY2hPWGxNd2dxOjE2MjIxNjA4MjU4MjU6MToxOmFjOjE
```

**3단계: POST oauth2/token - 액세스 토큰**

이제 인가 코드를 사용해 액세스 토큰과 리프레시 토큰을 생성할 수 있습니다 (`offline.access` 스코프를 요청한 경우에만 해당). 다음 엔드포인트로 POST 요청을 전송할 수 있습니다:

```
https://api.x.com/2/oauth2/token
```

요청 헤더를 통해 `Content-Type`으로 `application/x-www-form-urlencoded`를 전달해야 합니다. 추가로, 요청에는 `code`, `grant_type`, `client_id`, `redirect_uri`, 그리고 `code_verifier`가 포함되어야 합니다.

다음은 public client용 토큰 요청 예시입니다:

```json theme={null}
curl --location --request POST 'https://api.x.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'code=VGNibzFWSWREZm01bjN1N3dicWlNUG1oa2xRRVNNdmVHelJGY2hPWGxNd2dxOjE2MjIxNjA4MjU4MjU6MToxOmFjOjE' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ' \
--data-urlencode 'redirect_uri=https://www.example.com' \
--data-urlencode 'code_verifier=challenge'
```

다음은 confidential 클라이언트를 사용하는 예제입니다:

```json theme={null}
curl --location --request POST 'https://api.x.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic V1ROclFTMTRiVWhwTWw4M2FVNWFkVGQyTldNNk1UcGphUTotUm9LeDN4NThKQThTbTlKSXQyZm1BanEzcTVHWC1icVozdmpKeFNlR3NkbUd0WEViUA=='\
--data-urlencode 'code=VGNibzFWSWREZm01bjN1N3dicWlNUG1oa2xRRVNNdmVHelJGY2hPWGxNd2dxOjE2MjIxNjA4MjU4MjU6MToxOmFjOjE' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'redirect_uri=https://www.example.com' \
--data-urlencode 'code_verifier=challenge'
```

**4단계: API에 연결하기**

이제 OAuth 2.0을 사용해 엔드포인트에 연결할 준비가 되었습니다. 이를 위해 [Bearer Token 인증](/ko/resources/fundamentals/authentication/oauth-2-0/application-only)을 사용할 때와 동일한 방식으로 API 요청을 보내면 됩니다. 다만 Bearer Token을 전달하는 대신, 직전 단계에서 생성한 액세스 토큰을 사용해야 합니다. 응답으로는 요청한 엔드포인트에 해당하는 적절한 페이로드가 반환되어야 합니다. 이 요청 방식은 공개 클라이언트(public client)와 기밀 클라이언트(confidential client) 모두에 동일하게 적용됩니다. 

요청 예시는 다음과 같습니다:

```json theme={null}
curl --location --request GET 'https://api.x.com/2/tweets?ids=1261326399320715264,1278347468690915330' \
--header 'Authorization: Bearer Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'
```

**5단계: POST oauth2/token - refresh token**

refresh token을 사용하면 사용자의 추가 동의 없이도 애플리케이션이 새로운 access token을 발급받을 수 있습니다. refresh token은 다음 엔드포인트에 POST 요청을 보내 생성할 수 있습니다: [https://api.x.com/2/oauth2/token](https://api.x.com/2/oauth2/token) 헤더에 `Content-Type`으로 `application/x-www-form-urlencoded`를 추가해야 합니다. 추가로, `refresh_token`을 전달하고, `grant_type`을 `refresh_token`으로 설정하며, `client_id`를 지정해야 합니다.

이 요청은 공개 클라이언트(public client)에 대해 동작합니다:

```json theme={null}
POST 'https://api.x.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'refresh_token=bWRWa3gzdnk3WHRGU1o0bmRRcTJ5VUxWX1lZTDdJSUtmaWcxbTVxdEFXcW5tOjE2MjIxNDc3NDM5MTQ6MToxOnJ0OjE' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ'
```

다음은 기밀 클라이언트용 예시입니다.

```json theme={null}
POST 'https://api.x.com/2/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic V1ROclFTMTRiVWhwTWw4M2FVNWFkVGQyTldNNk1UcGphUTotUm9LeDN4NThKQThTbTlKSXQyZm1BanEzcTVHWC1icVozdmpKeFNlR3NkbUd0WEViUA=='\
--data-urlencode 'refresh_token=bWRWa3gzdnk3WHRGU1o0bmRRcTJ5VUxWX1lZTDdJSUtmaWcxbTVxdEFXcW5tOjE2MjIxNDc3NDM5MTQ6MToxOnJ0OjE'\
--data-urlencode 'grant_type=refresh_token'
```

**6단계: POST oauth2/revoke - 토큰 폐기**

revoke 토큰은 access 토큰이나 refresh 토큰을 무효화합니다. 이는 클라이언트에서 "로그아웃" 기능을 구현할 때 사용되며, 더 이상 필요하지 않을 수 있는 인가 플로와 연관된 보안 자격 증명을 정리할 수 있도록 해 줍니다. revoke 토큰은 사용자가 아니라 App이 토큰을 취소하기 위한 것입니다. App이 자신에게 부여된 액세스를 프로그래밍 방식으로 취소(revoke)하려는 경우, 다음 URL로 POST 요청을 보내 revoke 토큰 요청을 생성할 수 있습니다:

```
https://api.x.com/2/oauth2/revoke
```

헤더를 통해 `Content-Type`을 `application/x-www-form-urlencoded`로 지정하고, 토큰과 client\_id를 함께 전달해야 합니다.

경우에 따라 사용자가 App에 부여한 권한을 취소하고 싶을 수 있습니다. 이때 [Connected Apps 페이지](https://x.com/settings/connected_apps)를 방문하여 권한을 취소할 수 있습니다.

```bash theme={null}
curl --location --request POST 'https://api.x.com/2/oauth2/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'token=Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE' \
--data-urlencode 'client_id=rG9n6402A3dbUJKzXTNX4oWHJ'
```

이 요청은 confidential 클라이언트에서 사용할 수 있습니다:

```bash theme={null}
curl --location --request POST 'https://api.x.com/2/oauth2/revoke' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic V1ROclFTMTRiVWhwTWw4M2FVNWFkVGQyTldNNk1UcGphUTotUm9LeDN4NThKQThTbTlKSXQyZm1BanEzcTVHWC1icVozdmpKeFNlR3NkbUd0WEViUA=='\
--data-urlencode 'token=Q0Mzb0VhZ0V5dmNXSTEyNER2MFNfVW50RzdXdTN6STFxQlVkTGhTc1lCdlBiOjE2MjIxNDc3NDM5MTQ6MToxOmF0OjE'
```
