# TokenEndpoint

## Spring Authorization Server - 엔드포인트 프로토콜

## OAuth 2.0 Token Endpoint

### OAuth2TokenEndpointConfigurer

* OAuth2 토큰 엔드포인트에 대한 사용자 정의 할 수 있는 기능을 제공한다.
* OAuth2 토큰 요청에 대한 전처리, 기본 처리 및 후처리 로직을 커스텀하게 구현할 수 있도록 API를 지원한다.
* `OAuth2TokenEndpointFilter`를 구성하고 이를 OAuth2 인증 서버 `SecurityFilterChain` 빈에 등록한다.
* 지원되는 권한 부여 유형은 `authorization_code`, `refresh_token`, `client_credentials`, `device_code` 이다.

### OAuth2TokenEndpointFilter

* 클라이언트의 토큰 요청을 처리하는 필터이며 다음과 같은 기본값으로 구성된다.
  * **DelegatingAuthenticationConverter** - 각 특정 유형의 `AuthenticationConverter`를 호출해서 처리를 위임한다.
    * `OAuth2AuthorizationCodeAuthenticationConverter`
    * `OAuth2RefreshTokenAuthenticationConverter`
    * `OAuth2ClientCredentialsAuthenticationConverter`
    * `OAuth2DeviceCodeAuthenticationConverter`
    * 각 컨버터는 `HttpServletRequest` 정보를 `~~AuthenticationToken` 으로 변환하여 반환한다.
  * **AuthenticationProviders**
    * `OAuth2AuthorizationCodeAuthenticationProvider`
    * `RefreshTokenAuthenticationProvider`
    * `ClientCredentialsAuthenticationProvider`
    * `OAuth2DeviceCodeAuthenticationProvider`
    * 권한 부여 유형에 따라 토큰을 발행하는 `AuthenticationProvider` 구현체 들이다.
  * **AuthenticationSuccessHandler**
    * 인증된 `OAuth2AccessTokenAuthenticationToken`을 처리하는 내부 구현체로 인증 토큰을 사용하여 `OAuth2AccessTokenResponse`를 반환한다.
  * **AuthenticationFailureHandler**
    * `OAuth2AuthenticationException`과 관련된 `OAuth2Error` 응답을 반환한다.

### RequestMatcher

* **토큰 요청 패턴**
  * `/oauth2/token, POST`

***

### 사용자 정의 기능

![img\_21.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-7d5ad8479d9f00589086956a0c60aa01c215518a%2Fimg_21.png?alt=media)

1. `AuthenticationConverter` 추가
2. 스프링 시큐리티가 관리하는 `AuthenticationConverter` 들을 커스텀하게 변경 가능
3. `AuthenticationProvider` 추가
4. 스프링 시큐리티가 관리하는 `AuthenticationProvider` 들을 커스텀하게 변경 가능
5. `OAuth2AccessTokenAuthenticationToken` 을 처리하고 `OAuth2AccessTokenResponse`를 반환하는 데 사용되는 후처리기
6. `OAuth2AuthenticationException`을 처리하고 `OAuth2Error` 응답을 반환하는 데 사용되는 후처리기

***

## 클라이언트 인증하기

### OAuth2ClientAuthenticationConfigurer

* OAuth2 클라이언트 인증을 위한 사용자 정의 기능을 제공한다.
* 클라이언트 인증 요청에 대한 전처리, 기본 처리 및 후처리 로직을 커스텀하게 구현할 수 있도록 API를 지원한다.
* `OAuth2ClientAuthenticationFilter`를 구성하고 이를 OAuth2 인증 서버 `SecurityFilterChain` 빈에 등록한다.
* 지원되는 클라이언트 인증 방법은 `client_secret_basic`, `client_secret_post`, `private_key_jwt`, `client_secret_jwt`, `none(공개 클라이언트)`이다.

### OAuth2ClientAuthenticationFilter

* 클라이언트 인증 요청을 처리하는 필터로 다음과 같은 기본값으로 구성된다.
  * **DelegatingAuthenticationConverter**
    * `JwtClientAssertionAuthenticationConverter` : 클라이언트 요청 방식이 **HTTP Basic**일 경우 처리
    * `ClientSecretBasicAuthenticationConverter` : 클라이언트 요청 방식이 **POST**일 경우 처리
    * `ClientSecretPostAuthenticationConverter` : 클라이언트 요청 방식이 **JWT**일 경우 처리
    * `PublicClientAuthenticationConverter` : 클라이언트 요청 방식이 **PKCE**일 경우 처리
  * **AuthenticationProviders**
    * `JwtClientAssertionAuthenticationProvider`
    * `ClientSecretAuthenticationProvider`
    * `PublicClientAuthenticationProvider`
    * 권한 부여 유형에 따라 토큰을 발행하는 `AuthenticationProvider` 구현체들
  * **AuthenticationSuccessHandler**
    * 인증된 `OAuth2ClientAuthenticationToken`을 `SecurityContext`에 저장하는 내부 구현체
  * **AuthenticationFailureHandler**
    * `OAuth2AuthenticationException`을 사용하여 `OAuth2Error`를 반환하는 내부 구현체

### RequestMatcher

* **토큰 요청 패턴**
  * `/oauth2/token POST`
  * `/oauth2/introspect POST`
  * `/oauth2/revoke POST`
  * `/oauth2/device_authorization POST`

### 사용자 정의 기능

![img\_22.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-fe0927b42f488246d4aed57cca4f3884208e7aa7%2Fimg_22.png?alt=media)

1. `AuthenticationConverter` 추가
2. 스프링 시큐리티가 관리하는 `AuthenticationConverter` 들을 커스텀하게 변경 가능
3. `AuthenticationProvider` 추가
4. 스프링 시큐리티가 관리하는 `AuthenticationProvider` 들을 커스텀하게 변경 가능
5. `OAuth2ClientAuthenticationToken` 을 처리하는 데 사용되는 후처리기
6. `OAuth2AuthenticationException`을 처리하고 `OAuth2Error` 응답을 반환하는 데 사용되는 후처리기

***

## 클라이언트 인증 흐름

![img\_23.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-482fd117a2d6eb027ad148535cdc8671dd2dddf4%2Fimg_23.png?alt=media)

![img\_24.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-ae67621cac32f404c5fb8f9ee9a9488820d78c53%2Fimg_24.png?alt=media)

* 필터 체인에 등록된 필터들의 순서를 보면 토큰과 관련된 필터들은 모두 `AuthorizationFilter` 뒤에 있는 것을 확인할 수 있다.
* 즉 토큰을 요청하기 위해서는 클라이언트 인증이 우선적으로 이루어져야 하며, 클라이언트 인증은 `OAuth2ClientAuthenticationFilter`에서 이루어진다.

### 1. 임시 코드로 토큰 요청

![img\_25.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-beb215b4c7f2fb9653741a3ada2416d4661d1128%2Fimg_25.png?alt=media)

* `client_secret_post` 클라이언트 인증 방식

### 2. OAuth2ClientAuthenticationFilter -> ClientSecretPostAuthenticationConverter

![img\_26.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-50015656926ed9cdae7605ce7d3a77fbb3028a75%2Fimg_26.png?alt=media)

* 필요한 정보 추출 후 `OAuth2ClientAuthenticationToken` 생성

### 3. ProviderManager -> ClientSecretAuthenticationProvider

![img\_27.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-38f81bd867a7e10c2fc7e78296773fd6f02ce9e9%2Fimg_27.png?alt=media)

* `ClientSecretAuthenticationProvider`는 `client_secret_basic` 방식과 `client_secret_post` 방식을 처리한다.
* 인가 서버에 등록된 클라이언트 정보와 일치하는지 여러가지 정보들을 확인한다.
* 이후 최종적으로 인증된 `OAuth2ClientAuthenticationToken`을 반환한다.

### 4. OAuth2ClientAuthenticationFilter -> onAuthenticationSuccess()

![img\_28.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-f1cb75ec897a0ee203a7a24907d96c482840c09b%2Fimg_28.png?alt=media)

* 인증객체 저장

### 5. AuthorizationFilter -> OAuth2TokenEndpointFilter

* 클라이언트 인증을 마쳤으므로 `OAuth2TokenEndpointFilter`를 통해 최종 `OAuth2AccessTokenResponse` 반환

![img\_29.png](https://2900387690-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOjEy54f4ToLNl5n9gmZs%2Fuploads%2Fgit-blob-9b73222329e6dd2a5b951ac0c8532ddb206c640a%2Fimg_29.png?alt=media)

***

## 권한 부여 유형에 따른 코드 흐름

### [Authorization Code Endpoint 흐름](https://geun-00.gitbook.io/geun-00-docs/spring/security/oauth/springserver/endpoints/tokenendpoint)

### [Client Credentials Endpoint 흐름](https://geun-00.gitbook.io/geun-00-docs/spring/security/oauth/springserver/endpoints/tokenendpoint)

### [Refresh Token Endpoint 흐름](https://geun-00.gitbook.io/geun-00-docs/spring/security/oauth/springserver/endpoints/tokenendpoint)

### [Authorization Code with PKCE Endpoint 흐름](https://geun-00.gitbook.io/geun-00-docs/spring/security/oauth/springserver/endpoints/tokenendpoint)

***

[이전 ↩️ - Spring Authorization Server(엔드포인트 프로토콜) - AuthorizationServer Endpoint](https://github.com/genesis12345678/TIL/blob/main/Spring/security/oauth/SpringServer/Endpoints/AuthorizationServer.md)

[메인 ⏫](https://github.com/genesis12345678/TIL/blob/main/Spring/security/oauth/main.md)

[다음 ↪️ - Spring Authorization Server(엔드포인트 프로토콜) - Token Introspection Endpoint](https://github.com/genesis12345678/TIL/blob/main/Spring/security/oauth/SpringServer/Endpoints/Introspection.md)
