Spring Authorization Serverシリーズ①



# はじめに
2021年11月8日SpringオフィシャルサイトでSpring Security OAuth2.0のかわりにSpring Authorization Serverの使用を勧められました。
[Spring Security OAuth2.0](https://spring.io/projects/spring-security-oauth)
Spring Security OAuth2.0のEOLまで半年間ぐらいしか残っていないので、Spring Authorization Serverに切り替えましょう。

# 現在のSpring Security体系
Spring Security5.xはOAuth2.0 ClientとOAuth2.0 Resource Serverをモジュール化したので、Spring Securityを依存関係に追加しなければなりません。

```gradle:build.gradle
implementation 'org.springframework.boot:spring-boot-starter-security'
```

OAuth2.0 Clientを使う場合、、

```gradle:build.gradle
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
```


OAuth2.0 Resource Serverを使う場合、

```gradle:build.gradle
implementation 'org.springframework.boot:spring-boot-oauth2-resource-server'
```

現在、OAuth2.0 Authorization Serverを使う場合、以下の依存関係を追加すればいいです。

```gradle:build.gradle
//現在の最新バージョン
implementation 'org.springframework.security:spring-security-oauth2-authorization-server:0.2.0'
```
これで、OAuth2.0の三大ロールが揃いました。

# Spring Authorization Server
Spring Authorization Serverをデモにして、理解を深めましょう。
### デモの流れ
OAuth2.0の認可コードフローに対して、実装してみました。
[RFC 6749, 4.1. Authorization Code Grant] (https://datatracker.ietf.org/doc/html/rfc6749#section-4.1)
2つのプロジェクトで出来ております。

- oauth2-client:名前とおりにOAuth2.0 Clientで、Authorization ServerにAuthorizationリクエストする。
- oauth2-server:Spring Authorization Serverに基づく立ち上げたAuthorizationサーバ。

ユーザは/oauth2/authorization/{registrationId}エンドポイント経由でoauth2-clientにリクエストする：

```
GET /oauth2/authorization/felord HTTP/1.1
Host: 127.0.0.1:8080
```

OAuth2AuthorizationRequestRedirectFilterに捕獲された後、以下のリクエストを作成し、oauth2-serverにAuthorizationリクエストをする：

```
GET /oauth2/authorize?response_type=code&client_id=felord-client&scope=message.read%20message.write&state=0CI0ziUDEnqMgqW0nzRNRCzLrs-9IMbqJzGZ47Zb0gY%3D&redirect_uri=http://127.0.0.1:8080/foo/bar HTTP/1.1
Host: localhost:9000
```

oauth2-serverはこのリクエストを捕獲したら、該当ユーザは認可されたかどうかをチェックし、未認可の場合、401をスルーし，oauth2-serverのログイン画面に飛ばします。
それでユーザはログイン処理を行います：

```
POST /login HTTP/1.1
Host: localhost:9000
Content-Type: application/x-www-form-urlencoded

username=felord&password=password&_csrf=301a7baf-9e9a-4b17-acd4-613c809bf7f5
```
ログインが成功したら、302リダイレクトをし、/oauth2/authorizeの認可リクエストを続行します。
その際に、この認可リクエストはユーザの認可確認必要があるかどうかを判断し、デモの中で二回目の確認が必要があるので、以下の画面に飛ばします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311521/742597da-cdd5-95f0-810d-9542ce2af465.png)

認可を同意したら、認可サーバはredirect_uriを呼び出し、認可コードとstateを持ちながら、oauth2-clientにリクエストします。

```
GET /foo/bar?code=MCSJnvhXNyjilBaCyw1sCrrArWk1bzsEdxe5Z3EFbkdLwp8ASmum62n4M7Tz45VNpp_16IWboBnXlgG3LEfgN7MQqkf0-vVZufGrQpvRioRcBbesAiawMt4cspTk06ca&state=-fRunxjpG0aziPXnfcW1Iw1Fy_5_NwlUAgxABPOfAb8= HTTP/1.1 
Host: 127.0.0.1:8080
```
oauth2-clientのOAuth2AuthorizationCodeGrantFilterはredirect_uriへのリクエストを捕獲したら、認可サーバの/oauth2/tokenにリクエストします：

```
POST /oauth2/token?grant_type=authorization_code&code=MCSJnvhXNyjilBaCyw1sCrrArWk1bzsEdxe5Z3EFbkdLwp8ASmum62n4M7Tz45VNpp_16IWboBnXlgG3LEfgN7MQqkf0-vVZufGrQpvRioRcBbesAiawMt4cspTk06ca&redirect_uri=https://127.0.0.1:8080/foo/bar HTTP/1.1
Host: localhost:9000
Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ=
```

ここで使った認証方式はclient-authentication-method: client_secret_basicです。
認可サーバはtokenをクライアント側に返します。認証クライアント情報は：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311521/b657703f-c34c-5ee4-85cc-df6bdde51523.png)


ここでSpring Authorization Serverに基づく認可コードフローは完成できました。

## ご参考
[ソースコード](https://gitee.com/nicepear/security-learning/tree/spring-authorization-server/)
[元リンク](https://mp.weixin.qq.com/s/jtKgHFd3Sv_CpngvOruzww)