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)
}