Consider having JWTProcessor accept key set

Issue #296 resolved
Josh Cummings created an issue

Spring Security uses Nimbus in its Reactive stack for validating JWTs. Because querying the JWK Set Uri is a blocking operation, Spring leans heavily on a custom SecurityContext that contains the JWK set and a custom JWKSource that pulls the JWK set from that context:

class JWKContext implements SecurityContext {
    // holds list of JWKs
}

class JWKContextJWKSource implements JWKSource<JWKContext> {
    List<JWK> get(JWKSelector jwkSelector, JWKContext context) {
        // retreive JWK set from context
    }
}

...

// ... reactive call chain ...
.map(retreiveJwkSetReactively)
.map(JWKContext::new)
.map(context -> jwtProcessor.process(signedJwt, context))
// ...

What I'd like to do is be able to hand JWTProcessor some kind of key context, having already resolved the list of keys in another way.

I'm not certain that JWTProcessor#process(SignedJWT, List<JWK>, SecurityContext) is the right way to go, but it seems that passing in a parameter is more amenable than changing several Nimbus interfaces to be reactive.

Spring Security currently works with process(SignedJWT, SecurityContext), but is perhaps using SecurityContext in an unintended way to achieve the same end.

What do you think?

Comments (4)

  1. Vladimir Dzhuvinov

    Hi Josh,

    If I remember correctly, the SecurityContext was intended for exactly that sort of situation. So it should work. If you find any issues - let me know :)

  2. Josh Cummings reporter

    Hi, Vladimir. It does work, yes.

    Reading the Javadocs for SecurityContext, though, I was worried that passing a key set through that parameter was a bit of API abuse.

    It does surprise me to hear you say that pre-fetching keys is an intended use case for SecurityContext; I've always imagined it being a construct for shuttling around custom properties and the like.

    Thanks for taking a look.

  3. Josh Cummings reporter

    @vdzhuvinov I've created a pull request to contribute some code we've used to fulfill the use case described in this ticket. Let me know what you think!

  4. Log in to comment