Expected Behavior

Having ReactiveRemoteJWKSource public

Current Behavior

ReactiveRemoteJWKSource is package only accessible

Context

As it turns up, we are using the nimbus library for validating JWTs and we got the same requirements of having a RemoteJWKSet using Spring reactive. Seems you did all the hard work, it is just not accessible. Would it be possible to make it public?

btw, this is more a NimbusReactiveRemoteJWKSource if we follow your convention named you used for NimbusReactiveJwtDecoder.

Comment From: jzheaux

Hi, @qcastel, thanks for the suggestion.

As it turns up, we are using the nimbus library for validating JWTs and we got the same requirements of having a RemoteJWKSet using Spring reactive.

This sounds like what NimbusReactiveJwtDecoder was built for. For example:

NimbusReactiveJwtDecoder decoder = ReactiveJwtDecoders.fromIssuerLocation(...);
Mono<Jwt> decodeAndValidatedJwt = decoder.decode(encodedJwt); // decode and validate the JWT

What makes NimbusReactiveJwtDecoder unfit for what you are wanting to do?

Comment From: spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: qcastel

Hello @jzheaux,

In your above example, you return a org.springframework.security.oauth2.jwt.Jwt, which we are trying to avoid as we are using the Nimbus library too.

This is inconvenient for us to have to convert org.springframework.security.oauth2.jwt.Jwt into com.nimbusds.jwt.JWT, this is why we would prefer consuming directly ReactiveRemoteJWKSource

Thanks!

Comment From: jzheaux

Gotcha, @qcastel. If you are wanting to use Nimbus directly, I think the best source would be to raise an issue with the Nimbus team, since that's where Nimbus APIs should live. If you end up creating an issue, feel free to link it back here so others can continue to track progress.

I don't know if Nimbus already has reactive plans, but perhaps your use case can get the conversation started. Feel free to take anything applicable from ReactiveRemoteJWKSource to suit those needs.

FWIW, if you are in a position to change, some of the nice things about Spring's Jwt are the lack of checked exceptions in the getters, it's type-casting optimizations, and support for Instant, for example:

String subject;
Instant expiresAt;
try {
    subject = nimbusJWT.getJWTClaimsSet().getSubject();
    Date e = nimbusJWT.getJWTClaimsSet().getExpirationTime();
    if (e != null) {
        expiresAt = e.toInstant();
    }
} catch (ParseException e) {
    // handle
}

vs

String subject = springJwt.getSubject();
Instant expiresAt = springJwt.getExpiresAt();

But if not, I think you only need to do the conversion once with a custom JwtAuthenticationConverter:

public class JWTAuthenticationConverter implements Converter<Jwt, JWTAuthentication> {
    private final JwtAuthenticationConverter delegate = new JwtAuthenticationConverter();

    @Override
    public JWTAuthentication convert(Jwt springJwt) {
        Authentication authentication = delegate.convert(springJwt);
        JWT nimbusJWT = onetimeConversion(springJwt);
        return new JWTAuthentication(nimbusJWT, springJwt, authentication.getAuthorities());
    }
}

Following this pattern, you can still use NimbusReactiveJwtDecoder and only convert Jwt into JWT once.