Summary
I was trying to get Security Context in my WebFilter as you would typically do it:
chain.filter(exchange)
.subscriberContext(context -> {
context.getKey(SecurityContext.class);
//some work on context
});
Actual Behavior
Calling context.get(SecurityContext.class) causes java.util.NoSuchElementException: Context does not contain a value of type org.springframework.security.core.context.SecurityContext even though context.hasKey(SecurityContext.class) returns true (since ReactorContextWebFilter::withSecurityContext merges SecurityContext into Context).
The thing is, security context is present within the Context, but wrapped in Mono (see ServerSecurityContextRepository::load which returns mono, not SecurityContext).
The same issue makes ReactiveSecurityContextHolder::getContext() useless in WebFilters. It tries to load context just as i did in my filter and fails:
public static Mono<SecurityContext> getContext() {
return Mono.subscriberContext()
.filter( c -> c.hasKey(SECURITY_CONTEXT_KEY))
.flatMap( c-> c.<Mono<SecurityContext>>get(SECURITY_CONTEXT_KEY));
}
Expected Behavior
context.get(SecurityContext.class) returns SecurityContext or Mono<SecurityContext>, not thows an exception.
Configuration
Version
5.0.5.RELEASE
Sample
Filter below would cause an unexpected exception:
@Component
@Order(2)
public class SecurityContextExctractingFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return chain.filter(exchange)
.subscriberContext(context -> {
if (context.hasKey(SecurityContext.class)) {
SecurityContext secContext = context.get(SecurityContext.class);
}
return context.put("SomeString", "SomeObject");
}
);
}
}
Comment From: Sobakaa
Turns out i wasn't supplying a type properly. Using context.<Mono<SecurityContext>>get(SecurityContext.class) solves the issue. ReactiveSecurityContextHolder::getContext() not working properly is, again, a misuse on my side.
Comment From: Nida96
Can you elaborate your solution? As I too am facing this issue. specifically how are you making the getContext() call now.