最新の安定バージョンについては、Spring Security 7.0.0 を使用してください! |
OAuth 2.0 の変更
JwtTypeValidator で typ ヘッダーを検証する
Spring Security 7 の NimbusJwtDecoder は、typ ヘッダー検証を Nimbus ではなく JwtTypeValidator に移行します。これにより、NimbusJwtDecoder が Nimbus ではなく NimbusJwtDecoder でクレームを検証するのと同等になります。
jwtProcessorCustomizer メソッドで Nimbus のデフォルトの型検証を変更する場合は、それを JwtTypeValidator または独自の OAuth2TokenValidator の実装に移動する必要があります。
この変更の準備ができているかどうかを確認するには、デフォルトの JwtTypeValidator をバリデーターのリストに追加します。これは、7 ではデフォルトで含まれます。
Java
Kotlin
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.validateTypes(false) (1)
// ... your remaining configuration
.build();
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators(
new JwtIssuerValidator(location), JwtTypeValidator.jwt())); (2)
return jwtDecoder;
}
@Bean
fun jwtDecoder(): JwtDecoder {
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.validateTypes(false) (1)
// ... your remaining configuration
.build()
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators(
JwtIssuerValidator(location), JwtTypeValidator.jwt())) (2)
return jwtDecoder
}
| 1 | - Nimbus をオフにして typ を確認します (これは 7 ではデフォルトでオフになります) |
| 2 | - デフォルトの typ バリデーターを追加する (これは 7 ではデフォルトで含まれます) |
デフォルト値は、typ の値が JWT であるか存在しないかを確認します。これは Nimbus のデフォルトと同じです。また、typ はオプションであるとする RFC 7515 [IETF] (英語) と一致しています。
DefaultJOSEObjectTypeVerifier を使用しています
構成に次のようなものがある場合:
Java
Kotlin
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.jwtProcessorCustomizer((c) -> c
.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>("JOSE"))
)
.build();
return jwtDecoder;
}
@Bean
fun jwtDecoder(): JwtDecoder {
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.jwtProcessorCustomizer {
it.setJWSTypeVerifier(DefaultJOSEObjectTypeVerifier("JOSE"))
}
.build()
return jwtDecoder
}
これを次のように変更します。
Java
Kotlin
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.validateTypes(false)
.build();
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators(
new JwtIssuerValidator(location), new JwtTypeValidator("JOSE")));
return jwtDecoder;
}
@Bean
fun jwtDecoder(): JwtDecoder {
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.validateTypes(false)
.build()
jwtDecoder.setJwtValidator(JwtValidators.createDefaultWithValidators(
JwtIssuerValidator(location), JwtTypeValidator("JOSE")))
return jwtDecoder
}
typ ヘッダーがオプションであることを示すには、#setAllowEmpty(true) を使用します (これは、DefaultJOSEObjectTypeVerifier で許可される型のリストに null を含めることと同じです)。
オプトアウトしたい
これまで通りのやり方を続けたい場合は、手順は逆になりますが、同様です。
Java
Kotlin
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.validateTypes(true) (1)
.jwtProcessorCustomizer((c) -> c
.setJWSTypeVerifier(new DefaultJOSEObjectTypeVerifier<>("JOSE"))
)
.build();
jwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(
new JwtTimestampValidator(), new JwtIssuerValidator(location))); (2)
return jwtDecoder;
}
@Bean
fun jwtDecoder(): JwtDecoder {
val jwtDecoder = NimbusJwtDecoder.withIssuerLocation(location)
.validateTypes(true) (1)
.jwtProcessorCustomizer {
it.setJWSTypeVerifier(DefaultJOSEObjectTypeVerifier("JOSE"))
}
.build()
jwtDecoder.setJwtValidator(DelegatingOAuth2TokenValidator(
JwtTimestampValidator(), JwtIssuerValidator(location))) (2)
return jwtDecoder
}
| 1 | - Nimbus 型検証をオンのままにする |
| 2 | - JwtTypeValidator を除く必要なバリデータのリストを指定します |
追加のガイダンスについては、リファレンスの JwtDecoder バリデータセクションを参照してください。
Opaque トークン認証情報は暗号化されます
イントロスペクション RFC にさらに厳密に準拠するために、Spring Security の Opaque トークンサポートは、認証ヘッダーを作成する前にクライアント ID とシークレットをエンコードします。この変更により、クライアント ID とシークレットを自分でエンコードする必要がなくなります。
クライアント ID またはシークレットに URL に安全でない文字が含まれている場合は、次の操作を実行してこの変更に備えることができます。
introspectionClientCredentials の使用箇所の置き換え
Spring Security がエンコードを行えるようになったため、introspectionClientCredentials の使用を次の @Bean の公開に置き換えます。
Java
Kotlin
@Bean
OpaqueTokenIntrospector introspector() {
return SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectionUri)
.clientId(unencodedClientId).clientSecret(unencodedClientSecret).build();
}
@Bean
fun introspector(): OpaqueTokenIntrospector {
return SpringOpaqueTokenIntrospector.withIntrospectionUri(introspectionUri)
.clientId(unencodedClientId).clientSecret(unencodedClientSecret).build()
}
上記は 7.0 のデフォルトになります。
この設定で問題が発生する場合、または現時点では適用できない場合は、代わりに RestOperations コンストラクターを使用できます。
Java
Kotlin
@Bean
OpaqueTokenIntrospector introspector() {
RestTemplate rest = new RestTemplate();
rest.addInterceptor(new BasicAuthenticationInterceptor(encodedClientId, encodedClientSecret));
return new SpringOpaqueTokenIntrospector(introspectionUri, rest);
}
@Bean
fun introspector(): OpaqueTokenIntrospector {
val rest = RestTemplate()
rest.addInterceptor(BasicAuthenticationInterceptor(encodedClientId, encodedClientSecret))
return SpringOpaqueTokenIntrospector(introspectionUri, rest)
}