KeycloakのLogoutEndpointとTokenRevocationEndpointについて

## きっかけ
Keycloakのドキュメントにはリクエストエンドポイントの説明が記載されています。
ただ、メソッドやボディなど具体的にどのようにリクエストを実行すればいいのかがわからないのが悩みでした。
今回は[version 10.0.0](https://www.keycloak.org/docs/latest/release_notes/#keycloak-10-0-0)で実装されたToken Revocationエンドポイントが気になったので、Logoutエンドポイントと合わせて調べてみることにしました。

## やってみたこと
- LogoutエンドポイントとToken Revocationエンドポイントについて、ドキュメントやソースコードを確認して、リクエストを実行した結果をまとめてみました。

### Logoutエンドポイント
- 公式ドキュメントの説明
  - [Logoutエンドポイントの説明](https://www.keycloak.org/docs/latest/securing_apps/index.html#logout-endpoint-2)
  - [OIDCエンドポイントの一覧](https://www.keycloak.org/docs/latest/server_admin/index.html#keycloak-server-oidc-uri-endpoints)
- ソースコード
  - [Logoutエンドポイントのソースコードはここに記載されています。](https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java)
  - リクエストの仕方は2種類(GETリクエストとPOSTリクエスト)あります。
- Logoutエンドポイントについて
  - メタデータ(https://{KEYCLOAK URL}/auth/realms/{REALM NAME}/.well-known/openid-configuration)を確認すると、このLogoutエンドポイントが OIDC の end_session_endpoint となっています。
  - end_session_endpoint については [OpenID Connect Session Management 1.0 の RP-Initiated Logout](https://openid.net/specs/openid-connect-session-1_0.html#RPLogout)に記載されています。

#### [GET リクエスト](https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java#L101)
1つ目はGETでリクエストする方法です。ブラウザベースでアクセスさせる場合に利用します。

Keycloakのアカウント画面からサインアウトボタンを押下すると、このリクエストが実行されることになります。

` https://keycloak.example.com/auth/realms/master/protocol/openid-connect/logout?redirect_uri=https%3A%2F%2Fkeycloak.example.com%2Fauth%2Frealms%2Fmaster%2Faccount%2F `

- Method
  - GET
- URL
  - /realms/{realm-name}/protocol/openid-connect/logout
- Parameter
  - id_token_hint：OpenID Connect Session Management記載
     - OIDCで取得したIDTokenをセット
     - OPはログアウトをしているユーザを特定するために利用
  - post_logout_redirect_uri：OpenID Connect Session Management記載
     - ログアウト後に遷移するURL
     - このURLはクライアントの「有効なリダイレクトURL」に事前に設定要
     - Keycloakのアカウント画面の場合、` account ` というクライアントに ` /realms/master/account/* ` が設定されています
     - そのため、ログアウトリクエスト実施後にKeycloakのログイン画面に遷移することができるようになっています
  - state：OpenID Connect Session Management記載
     - post_logout_redirect_uriに指定したURIに渡す値を指定
  - initiating_idp：Keycloakの独自パラメータ
     - [外部IdPからログアウトされないようにする外部IdPのエイリアスを指定](https://keycloak-documentation.openstandia.jp/master/ja_JP/securing_apps/index.html#%E3%83%AD%E3%82%B0%E3%82%A2%E3%82%A6%E3%83%88)
     - initiating_idpパラメータがないとアイデンティティプロバイダーで登録したシングルログアウトエンドポイントにリクエストを行い、ログアウトを行おうとします。
  - redirect_uri ※deprecated
     - post_logout_redirect_uri を利用できるため、redirect_uriについてはdeprecatedとなっているようです

#### [POST リクエスト](https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/protocol/oidc/endpoints/LogoutEndpoint.java#L181)

- バックチャネル用のログアウトエンドポイントで、HTTPSでリクエストする必要があります。

- Method
  - POST
- URL
  - /realms/{realm-name}/protocol/openid-connect/logout
- Header
  - Content-Type: application/x-www-form-urlencoded
  - Confidential Clientの場合はクライアントの認証が必要です。
    - クライアントの認証タイプがClient Id And Secret&Authorizationヘッダーの場合
      - Authorization: Basic {client_id}:{client_secret}をBase64Encodeしたもの
  - Public Clientの場合はクライアントIDのみとなります。
      - Authorization: Basic {client_id}:をBase64Encodeしたもの
- Body
  - ` refresh_token={refresh_token} `
  - クライアント認証を含める場合は ` client_id={client_id}&client_secret={client_secret}&refresh_token={refresh_token} ` をBodyにします。

- Response ステータスコード
  - 204 (Success)
  - 400 (Error)

### Token Revocation エンドポイント
こちらは[RFC7009(OAuth 2.0 Token Revocation)](https://tools.ietf.org/html/rfc7009#section-2.1)のエンドポイントです。

- 公式ドキュメントの説明
  - [Token Revocation エンドポイントの説明](https://www.keycloak.org/docs/latest/securing_apps/index.html#_token_revocation_endpoint)
  - [OIDCエンドポイントの一覧](https://www.keycloak.org/docs/latest/server_admin/index.html#keycloak-server-oidc-uri-endpoints)
- ソースコード
  - [Token Revocation エンドポイントのソースコードはここに記載されています。](https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java)
- 詳細
  - [KEYCLOAK-5325 Provide OAuth token revocation capabilityのPullRequestに記載されています。](https://github.com/keycloak/keycloak/pull/6704#issue-368868115)

#### [リクエスト](https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/protocol/oidc/endpoints/TokenRevocationEndpoint.java#L83)

- HTTPSでリクエストする必要があります。

- Method
  - POST
- URL
  - /realms/{realm-name}/protocol/openid-connect/revoke
- Header
  - Content-Type: application/x-www-form-urlencoded
  - Confidential Clientの場合はクライアントの認証が必要です。
    - クライアントの認証タイプがClient Id And Secret&Authorizationヘッダーの場合
      - Authorization: Basic {client_id}:{client_secret}をBase64Encodeしたもの
  - Public Clientの場合はクライアントIDのみとなります。
      - Authorization: Basic {client_id}:をBase64Encodeしたもの
- Body
  - ` token={refresh_token}&token_type_hint=refresh_token ` ※toke_type_hintは指定してもKeycloakは無視します。
  - クライアント認証を含める場合は ` client_id={client_id}&client_secret={client_secret}&token={refresh_token} ` をBodyにします。

- Response ステータスコード
  - 200
     - 不適切なトークンを指定してもスタータスコードは200のままで以下のレスポンスを返す
     - ` {"error":"invalid_token","error_description":"Invalid token"} `


~~[現在TokenRevocationエンドポイントはMetadataには記載されていません。] (https://github.com/keycloak/keycloak/pull/6704#issuecomment-580075342)~~
[※Keycloak 12.0 よりメタデータに追加されました！](https://github.com/keycloak/keycloak/pull/7106)