はじめに
2021年11月8日SpringオフィシャルサイトでSpring Security OAuth2.0のかわりにSpring Authorization Serverの使用を勧められました。
Spring Security OAuth2.0
Spring Security OAuth2.0のEOLまで半年間ぐらいしか残っていないので、Spring Authorization Serverに切り替えましょう。
現在のSpring Security体系
Spring Security5.xはOAuth2.0 ClientとOAuth2.0 Resource Serverをモジュール化したので、Spring Securityを依存関係に追加しなければなりません。
implementation 'org.springframework.boot:spring-boot-starter-security'
OAuth2.0 Clientを使う場合、、
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
OAuth2.0 Resource Serverを使う場合、
implementation 'org.springframework.boot:spring-boot-oauth2-resource-server'
現在、OAuth2.0 Authorization Serverを使う場合、以下の依存関係を追加すればいいです。
//現在の最新バージョン
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の認可リクエストを続行します。
その際に、この認可リクエストはユーザの認可確認必要があるかどうかを判断し、デモの中で二回目の確認が必要があるので、以下の画面に飛ばします。
認可を同意したら、認可サーバは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をクライアント側に返します。認証クライアント情報は:
ここでSpring Authorization Serverに基づく認可コードフローは完成できました。