Spring Boot JWT の短命トークン設計をコードで読む
murraco/spring-boot-jwtは実運用向けに使える実用的なオープンソース実装で、再利用可能な導入ルートを持つプロジェクトです。
ひと目でわかる
- これは何?
- アクセストークンとローテーション式リフレッシュトークンを扱う Spring Boot サンプル。認証フロー、失効管理、設定上の確認点を整理する。
- 誰に向いている?
- README は最後に貢献の依頼とコーヒーのリンクで締めくくられており、このリポジトリは本番デプロイの文書化ではなくデモンストレーションの位置づけです。 採用前には、失効済みリフレッシュトークンの再利用と署名鍵の更新をテストケースに加え、サンプルの安全境界を自分の認証要件と照合したい。
- 商用利用できる?
- できます。MIT は寛容なライセンスで、著作権表示とライセンス表示を残せば、使用・改変・販売が可能です。
- 今もメンテナンスされている?
- されています。最後のコミットは 15 日前です。
- 何の言語で書かれている?
- 主に Java です(GitHub の言語統計による)。
回答はプロジェクトの GitHub データ(最終同期:2026年9月14日)と当サイトの分析に基づくもので、法的助言ではありません。
オープンソース詳細解説
開発用 H2 プロファイルを持つ Spring Boot 3.5 JWT サービス
リポジトリのメタデータは、Spring Boot・Spring Security・MySQL を使った JWT 認証サービスと説明しています。README のスタック一覧には Java 17、Spring Boot 3.5、MySQL、JWT、リフレッシュトークン、SpringDoc OpenAPI が並びます。デフォルトの開発プロファイルはインメモリの H2 データベース(test_db)を使い、H2 コンソールが有効です。MySQL の URL はコメントアウトされた例にだけ出てきます。このプロジェクトは Spring Boot 3.5.x、Java 17+、Spring Security 6、Jakarta EE 名前空間、JJWT 0.12.x、SpringDoc を対象としています。この記事を書いた時点で、リポジトリのスターは 1,686、フォークは 651、未解決の issue は 1 件です。
アクセストークンとリフレッシュトークンの流れ
この API はアクセストークンとリフレッシュトークンを組み合わせたパターンを実装しています。POST /users/signin でサインインすると、accessToken、refreshToken、tokenType、expiresIn を含む JSON オブジェクトが返ります。アクセストークンは短命でステートレスな JWT であり、各リクエストで Authorization: Bearer <token> として送ります。リフレッシュトークンは長期の不透明なランダム文字列で、サーバー側に保存され、新しいアクセストークンを得るためだけに使われます。/users/signin、/users/signup、/users/refresh、/users/logout は公開エンドポイントで、それ以外はすべて有効なアクセストークンを要求します。ROLE_ADMIN や ROLE_CLIENT などのロールは、コントローラメソッドの @PreAuthorize で強制されます。README のシーケンス図は、サインイン、保護リクエスト、リフレッシュのローテーションを示しています。
リフレッシュトークン設計: 不透明・ハッシュ化・単回使用
リフレッシュトークンは SecureRandom で生成した 256 ビットの乱数で、Base64url でエンコードされ、クレームを持ちません。その意味は指し示すデータベースの行だけにあります。保存されるのは SHA-256 ハッシュのみで(RefreshToken.tokenHash)、データベースが漏れても使えるトークンは直接手に入りません。リフレッシュのたびに提示されたトークンは消費され、代わりに新しいトークンが返ります。すでに消費されたトークンが再度提示されると、サービスはそのユーザーのすべてのリフレッシュトークンを失効させ、リクエストを拒否して再サインインを要求します。README はトレードオフも指摘しています。JWT_EXPIRE_MS を短くすると盗まれたアクセストークンが使える時間が狭まる一方、リフレッシュの往復が増えます。アクセストークン自体は期限が切れるまで失効させられません。
セキュリティパッケージの主要クラス
JwtTokenFilter は、4 つの未認証エンドポイント以外のすべての API パスに適用されます。その 4 つは permitAll ではなく shouldNotFilter でスキップされます。理由は、期限切れセッションをリフレッシュするクライアントが古い Authorization ヘッダをまだ付けていることが多く、フィルタが無効なトークンを拒否するためです。フィルタは JwtTokenProvider でトークンを解決・検証し、プロバイダが署名を検証して ID と認可クレームを取り出します。RefreshTokenService は issue、rotate、revoke、deleteAllForUser を管理します。rotate には dontRollbackOn = CustomException が付いており、リプレイされたトークンが例外を起こしても、失効処理自体はロールバックされません。MyUserDetails は UserDetailsService を実装し、WebSecurityConfig はステートレスセッション、CSRF 無効、requestMatchers、JWT フィルタを UsernamePasswordAuthenticationFilter の前に追加する SecurityFilterChain を定義します。
デモの実行と本番設定
README のセットアップ手順では JDK 17 以降と Maven 3.6.3+ が必要です。同梱の mvnw ラッパーも使えます。クローンして mvn install を実行し、mvn spring-boot:run でポート 8080 にアプリが起動します。Swagger UI は http://localhost:8080/swagger-ui.html、OpenAPI JSON は /v3/api-docs にあります。起動時に admin/admin123456 と client/client123456 の 2 つのデモユーザーが冪等に作成されます。設定は環境変数で制御します。JWT_SECRET(デフォルト secret-key、開発のみ)、JWT_EXPIRE_MS(デフォルト 300000、5 分)、JWT_REFRESH_EXPIRE_MS(デフォルト 604800000、7 日)です。本番では長いランダムなシークレットを設定し、H2 コンソールを無効にし、実データベースを使うよう README は指示しています。Docker は docker build -t spring-boot-jwt . と docker run -p 8080:8080 spring-boot-jwt です。
テストとリフレッシュ処理の破壊的変更
テストは ./mvnw test で実行します。UserControllerTest は @SpringBootTest と MockMvc を使った統合スタイルのテストで、サインイン/サインアップ、ロール保護エンドポイント、リフレッシュのローテーション、リプレイされたトークンの拒否、再利用検出後の全トークン族の失効、ログアウト、そして Authorization ヘッダに期限切れアクセストークンが付いた状態でのリフレッシュをカバーします。README は既存の fork への破壊的変更も記録しています。サインインとサインアップは裸の文字列ではなく JSON トークンペアを返すようになり、GET /users/refresh は削除されて POST /users/refresh に置き換わりました。新しい POST /users/logout はリフレッシュトークンを失効させます。Spring Boot 2.x からのアップグレードは、javax.* から jakarta.* への移行、SecurityFilterChain の採用、Springfox から SpringDoc への交換、JJWT 0.12+ への更新、JDK 17+ での実行が必要です。
ライセンスと README が主張していないこと
このプロジェクトは MIT ライセンスで公開されており、Copyright (c) 2017 Mauricio Urraco です。ライセンスは、著作権表示を含めることを条件に、使用、複製、変更、結合、公開、配布、再許諾、販売を許可します。ソフトウェアは現状のまま提供され、いかなる保証もありません。README の貢献セクションは問題報告、プルリクエスト、口コミを求めていますが、本番展開、性能ベンチマーク、セキュリティ監査については記述がありません。リポジトリのメタデータには、この記事を書いた時点で未解決の issue が 1 件あります。
編集部の結論
README は最後に貢献の依頼とコーヒーのリンクで締めくくられており、このリポジトリは本番デプロイの文書化ではなくデモンストレーションの位置づけです。 採用前には、失効済みリフレッシュトークンの再利用と署名鍵の更新をテストケースに加え、サンプルの安全境界を自分の認証要件と照合したい。
コミュニティノート