We use WebClient in servlet environment.
Some of our ExchangeFilterFunction requires current authentication object as well as values associated to the http request.
Previously, with RestTemplate, we used ThreadLocal to hold and retrieve request bounded values.(RequestContextHolder, SecurityContextHolder, etc.)
With WebClient, Spring Security's SecurityReactorContextSubscriber in SecurityReactorContextConfiguration exposes auth, servlet request, and servlet response in a Map(called ContextAttributes) to the subscriber context.
In our custom filter functions, we leverage this context-attributes-map to retrieve auth and request bounded values similar to what ServletBearerExchangeFilterFunction does.
Currently, to access this context-attributes-map, the key SECURITY_CONTEXT_ATTRIBUTES is defined as package private in SecurityReactorContextConfiguration.
static final String SECURITY_CONTEXT_ATTRIBUTES = "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES";
Even within Spring Security, ServletBearerExchangeFilterFunction(oauth2-resource-server module) and ServletOAuth2AuthorizedClientExchangeFilterFunction(oauth2-client module) which define same String constant key in order to access this context-attributes-map.
This is probably due to the SECURITY_CONTEXT_ATTRIBUTES constant is defined in SecurityReactorContextConfiguration(config module) which is a downstream module(and class is package private).
So, to allow context-attributes-map being used not only by oauth2-[resource-server|client] modules, but also user library/application, can this SECURITY_CONTEXT_ATTRIBUTES constant (and maybe mechanism around) be exposed to somewhere in upstream module public class?
Also, the context-attributes-map can be an independent class instead of generic Map to enhance accessibility of stored objects.
Ideally, I think this infrastructure(subscriber, lifter, context-attributes-map) is available in Spring Framework; then, Spring Security adds a logic to populate SecurityContext on it. (https://github.com/spring-projects/spring-framework/issues/25710)
Comment From: jgrandja
@ttddyy SecurityReactorContextConfiguration is meant to be used internally within the framework only so it is unlikely that we would expose this.
Even though SECURITY_CONTEXT_ATTRIBUTES is package-private, could you not simply obtain the Map of context attributes using context.get("org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES")? This should work.
Comment From: ttddyy
Yeah, I have a utility class that uses the String key "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES" to retrieve Authentication from reactor context.
This works but since it is bit of internal to the spring security, it would be nice to have public(official) way of getting Authentication(as well as HttpServletRequest and HttpServletResponse) in WebClient filters in servlet environment.
I think it is in common needs getting Authentication when writing a custom WebClient filters.
Comment From: jgrandja
@ttddyy
As mentioned in previous comment...
SecurityReactorContextConfigurationis meant to be used internally within the framework only so it is unlikely that we would expose this.
We might consider extracting the SecurityReactorContextConfiguration.SecurityReactorContextSubscriber.SECURITY_REACTOR_CONTEXT_ATTRIBUTES_KEY to another class/interface so it's publicly accessible. Do you have a suggestion?
Comment From: ttddyy
I don't have any specific candidate class/interface for holding the key. Probably new class/interface.
Just quickly saw the module structure, I think either spring-security-oauth2-core or spring-security-web module seems to be a good place.
They are available to reference the key to
- oauth2-client module for ServletOAuth2AuthorizedClientExchangeFilterFunction
- oauth2-resource-server module for ServletBearerExchangeFilterFunction
- config module for SecurityReactorContextConfiguration.SecurityReactorContextSubscriber
Comment From: jgrandja
@ttddyy As mentioned in this comment:
SecurityReactorContextConfigurationis meant to be used internally within the framework only so it is unlikely that we would expose this.
It doesn't make sense to expose it at this point.
I have a utility class that uses the String key "org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES" to retrieve Authentication from reactor context. This works but since it is bit of internal to the spring security, it would be nice to have public(official) way of getting Authentication(as well as HttpServletRequest and HttpServletResponse) in WebClient filters in servlet environment.
If you have another suggestion on making it easier for obtaining Authentication, HttpServletRequest and HttpServletResponse then please submit a PR and we can work from there.
I'm going to close this as exposing SECURITY_CONTEXT_ATTRIBUTES doesn't make sense at this point.