For resource server, it's as simple as
@Bean
fun jwtDecoder(): JwtDecoder {
// makes a request to the JWK Set endpoint
val jwsKeySelector: JWSKeySelector<SecurityContext> = JWSAlgorithmFamilyJWSKeySelector.fromJWKSetURL<SecurityContext>(this.jwkSetUrl)
val jwtProcessor: DefaultJWTProcessor<SecurityContext> = DefaultJWTProcessor()
jwtProcessor.jwsKeySelector = jwsKeySelector
return NimbusJwtDecoder(jwtProcessor)
}
and it fetches the algorithms from the public key endpoint.
But it doesn't work for OidcIdTokenDecoderFactory because https://github.com/spring-projects/spring-security/blob/6.0.0-M6/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/authentication/OidcIdTokenDecoderFactory.java create a new JwtDecoder
Any idea? or I can only customize a OidcIdTokenDecoderFactory
?
The OidcIdTokenDecoderFactory
is indeed the correct configuration hook for providing the algorithm used for a client in a custom way.
For example, you can specify the following:
@Bean
public JwtDecoderFactory<ClientRegistration> idTokenDecoderFactory() {
OidcIdTokenDecoderFactory idTokenDecoderFactory = new OidcIdTokenDecoderFactory();
idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration -> {
@SuppressWarnings("unchecked")
List<String> supportedAlgorithms =
(List<String>) clientRegistration.getProviderDetails()
.getConfigurationMetadata()
.get("id_token_signing_alg_values_supported");
return SignatureAlgorithm.from(supportedAlgorithms.get(0));
});
return idTokenDecoderFactory;
}
Note that this is a trivial example that assumes the first available algorithm. You can provide any logic you need, but it has to return a single algorithm.
There is some good background on this issue in #11049.