Skip to content

Spring Security 6 でのJWT設定

問題

Spring Security 6.0で既存のJWT設定コードが非推奨になり、エラーが発生するケースが増えています。特に以下の点で問題が発生します:

  • OAuth2ResourceServerConfigurer::jwt メソッドの非推奨化
  • antMatchers(), mvcMatchers(), regexMatchers() メソッドの完全削除
  • 設定方法全体がラムダ式ベースのDSLに移行

典型的なエラー例(非推奨の設定):

java
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    // ... 他の設定 ...
    http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); // 非推奨!
    return http.build();
}

移行の必要性

Spring Security 5.8では非推奨警告が表示されますが、6.0では完全に動作しなくなります。既存の設定は早期の修正が必要です。

解決策:新しいJWT設定方法

Spring Security 6.xではラムダ式ベースのDSLを使用した設定が必須です。以下のいずれかの方法で実装します。

方法1: デフォルト設定を使用(推奨)

java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));
    
    return http.build();
}

方法2: カスタムJwtDecoderを設定

java
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
        .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder())));
    
    return http.build();
}

@Bean
public JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder
        .withJwkSetUri("https://auth-server-url/.well-known/jwks.json")
        .build();
}

設定のポイント

  • Customizer.withDefaults(): SpringのデフォルトJWT処理を適用
  • カスタムDecoderが必要な場合は直接jwt.decoder()を実装
  • requestMatchers() で新しいエンドポイント指定を追加可能
    java
    .authorizeHttpRequests(auth -> auth
        .requestMatchers("/public/**").permitAll()
        .anyRequest().authenticated()
    )

Kotlinでの実装例

kotlin
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
    http
        .authorizeHttpRequests { auth ->
            auth
                .requestMatchers("/api/**").authenticated()
                .anyRequest().permitAll()
        }
        .oauth2ResourceServer { oauth2 ->
            oauth2.jwt(Customizer.withDefaults())
        }
    
    return http.build()
}

移行ガイダンス

1. メソッドチェーンからラムダ式へ

非推奨の書き方新しい書き方
.and()ラムダ式のネスト化で不要に
httpBasic()httpBasic { ... }
oauth2ResourceServer().jwt()oauth2ResourceServer { it.jwt { ... } }

2. エンドポイント指定の変更

java
// 古い書き方 (削除済み)
.antMatchers("/admin/**").hasRole("ADMIN")

// 新しい書き方
.requestMatchers("/admin/**").hasRole("ADMIN")

3. 依存関係の更新

Spring Boot 3.x以上を使用していることを確認:

gradle
// build.gradle
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-security:3.1.0'
    implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'
}

注意点

  • Spring Security 5.8→6.0への直接移行は非推奨
  • 公式が推奨する移行パス:
  • 移行中は公式移行ガイドを参照

ベストプラクティス

  1. JWTデコーダの外部設定
java
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") 
String jwksUri;

@Bean
public JwtDecoder jwtDecoder() {
    return NimbusJwtDecoder.withJwkSetUri(jwksUri).build();
}
  1. カスタム認証エラー処理
java
.oauth2ResourceServer(oauth2 -> oauth2
    .jwt(Customizer.withDefaults())
    .authenticationEntryPoint((req, res, ex) -> {
        res.sendError(HttpStatus.UNAUTHORIZED.value());
    })
)
  1. プロファイル別設定
java
@Profile("!prod")
@Bean
public SecurityFilterChain localFilterChain(HttpSecurity http) /* ... */

@Profile("prod")
@Bean
public SecurityFilterChain prodFilterChain(HttpSecurity http) /* ... */

これらの設定により、Spring Security 6.xの新アーキテクチャに準拠した安全なJWT認証を実装できます。