この記事はSRA Advent Calendar 2023の1日目の記事です。
こんにちは! 関西事業部の佐々木です。
SpringBootでgRPCアプリを
RESTアプリケーションなど、SpringBootを使ってWebアプリを作るのに慣れているJava技術者は少なくないはずです。
gRPCアプリを作る時にも慣れ親しんだSpringを使いたいと思うのは自然でしょう。
SpringBootを使ってgRPCアプリケーションを作るのは簡単で、LogNetのgrpc-spring-boot-starter([https://github.com/LogNet/grpc-spring-boot-starter] (https://github.com/LogNet/grpc-spring-boot-starter)) を依存関係に追加します。
gradleなら
dependencies {
implementation 'io.github.lognet:grpc-spring-boot-starter:5.1.5'
}
と設定し、protoファイルから生成した XxxGrpc.XxxImplBase クラスを継承して実装するだけです。
これでSpringBootを使ってgRPCアプリケーションは作成できるのですが、その作ったgRPCアプリでAuth0を認可サーバとしてJWT検証を組み込みたい場合はどうすればいいでしょうか。
実はネットで検索するとそれなりに情報がヒットするのですが、意外とストレートに解説している記事は少ないです。上記のLogNetのgrpc-spring-boot-starterでは「10. Spring Security Integration」の項目で Basic, Bearer, Custom のスキーマについて必要な依存ライブラリが記載させています。
gRPCのAuth0によるJWT検証ではメタデータに「Authorization」というキーに「Bearer <Auth0発行のJWT>」という値を設定してリクエストを行いますので、これらのうち「Bearer」が該当します。
そこでBearerに必要な依存ライブラリを見ると
- org.springframework.security:spring-security-config
- org.springframework.security:spring-security-oauth2-jose
- org.springframework.security:spring-security-oauth2-resource-server
と書かれています。
これら3つのライブラリを馬鹿正直に設定してもいいのですが、私のような面倒くさがりは
- org.springframework.boot:spring-boot-starter-oauth2-resource-server
の一つの設定で済ますのが楽でしょう。
(この設定で上記3つのライブラリも追加されます)
これらのライブラリが依存関係に追加されると、Spring Securityの検証処理が実行されます。
(なのでこのままでは呼び出してもUNAUTHENTICATEDエラーが返ってきます)
次に必要な設定はJWKSを取得するためのサーバ(認可サーバ)としてAuth0のURLをapplication.ymlに設定します。
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://osakeganomitai.jp.auth0.com/
spring.security.oauth2.resoruceserver.jwt.issuer-uriがAuth0のサーバを設定するキーです。
最後のスラッシュ「/」を忘れないようにしてください。
アプリ側としては以上で終わりです。
アプリケーションを起動し、gRPCメタデータにJWTをセットしてリクエストを実行してみてください。
UNAUTHENTICATEDエラーにならなければ成功です。
SpringBootTestはどうするか
普通のメソッド単位の単体テストなら関係ないですが、@SpringBootTest
によるテストの場合、実際にこのアプリケーションが起動しますので、JWT検証の機能が動きます。
単体テストコードの中でAuth0にアクセスしJWTを取得すれば問題ないですが、色々と面倒です。
こういった場合、src/main/resources
でなく src/test/resources
の下にapplication.ymlを作成し、
grpc:
security:
auth:
enabled: false
と設定することでテスト実行時のみJWT検証を無効化できます。
以上、参考になれば幸いです。