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 型検証をオンのままにする
2JwtTypeValidator を除く必要なバリデータのリストを指定します

追加のガイダンスについては、リファレンスの 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)
}