-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Common hook/listener for authentication results for inbound requests #14046
Comments
Hi, @philsttr. I believe you would be able to do it by relying on the @Bean
static SecurityContextHolderStrategy securityContextHolderStrategy() {
SecurityContextHolderStrategy original = SecurityContextHolder.getContextHolderStrategy();
SecurityContextChangedListener listener = new MyListener();
SecurityContextHolderStrategy strategy = new ListeningSecurityContextHolderStrategy(original, listener);
SecurityContextHolder.setContextHolderStrategy(strategy);
return strategy;
}
static class MyListener implements SecurityContextChangedListener {
@Override
public void securityContextChanged(SecurityContextChangedEvent event) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes != null) {
// there is a request bound to the thread
// you can even check if requestAttributes instanceof ServletRequestAttributes
}
}
} @jzheaux do you have any other suggestions on how to achieve this? |
Thanks for the response @marcusdacoregio. A couple problems with that approach:
|
What do you mean by successful authentication? Do you want to capture those attributes only when the user performs the authentication? Or, if the session contains an authenticated security context, would you consider that too? Have you considered implementing a filter that captures the attributes for each request? |
Excellent questions. I'll clarify. I want to capture the attributes for each inbound request that has an associated I have not considered implementing a filter, because I'm not quite sure how the OpenTelemetry Java Agent instrumentation could inject that filter into the "right" spot in the filter chain for all (or at least the vast majority of) apps. The agent is intended to "just work" when enabled for an application, so it is important that it works in a wide variety of apps. The agent can easily inject bytecode at strategic spots that would work across all/majority of apps. It seemed easier to me for the agent to inject some bytecode, rather than manipulate one or more filter chains in an app. |
You got me thinking about filters. Perhaps the agent could instrument the |
Sounds like a good place to do it. I think that for servlet apps you should place your filter before the |
Got it, yeah I was looking at the reactive filter chain. I assumed the servlet was similar, but it's a bit different as you mentioned. I have a working implementation of the reactive instrumentation (will be contributing it as part of open-telemetry/opentelemetry-java-instrumentation#9400). It's pretty clean, and I'm pretty happy with it. So I'm going to close this issue. Thanks for the brainstorming and the help! |
For reference: open-telemetry/opentelemetry-java-instrumentation#9777 adds the OpenTelemetry instrumentation described above |
I've been looking into adding instrumentation to OpenTelemetry to capture the
enduser.id
,enduser.role
, andenduser.scope
attributes as part of Server spans for applications using Spring Security. In Spring Security terms, this means retrieving theAuthentication
principal name, roles, and scopes from theAuthentication
object obtained for a successful authentication for inbound requests. I'm trying to identify the best location in Spring Security to instrument to capture those attributes from anAuthentication
object.I have found is that there is no "single place" to capture the Authentication object that results from successful authentications for inbound requests.
I considered instrumenting
SecurityContext
orReactiveSecurityContext
to capture theAuthentication
from when theSecurityContext
orReactiveSecurityContext
is written. But, unfortunately, they can be written in places that aren't just for inbound requests. For example, it could be for async processing, or scheduled tasks, or the application could even switch the active authentication during request processing for impersonation. Therefore, this would catch more use cases than desired.Next, I looked at all the places that perform authentication for inbound requests. Some examples:
Reactive:
AuthenticationWebFilter.authenticate
OAuth2AuthorizationCodeGrantWebFilter.authenticate
Servlet:
AuthenticationFilter.attemptAuthentication
AbstractPreAuthenticatedProcessingFilter.doAuthenticate
AbstractAuthenticationProcessingFilter.doFilter
RememberMeAuthenticationFilter.doFilter
BasicAuthenticationFilter.doFilterInternal
BearerTokenAuthenticationFilter.doFilterInternal
OAuth2AuthorizationCodeGrantFilter.processAuthorizationResponse
So, one option would be to add OpenTelemetry instrumentation to each of these places. While this is possible, it's not ideal because it is very fragile. For example, new filters that authenticate inbound requests won't be covered, and any changes to any of those locations could also break the instrumentation. It also requires different strategies in each case for actually capturing the
Authentication
object, since not every location encapsulates theAuthentication
object in the same way.What I would really love is some kind of hook or listener that the instrumentation could use to listen for successful authentications for inbound requests. Perhaps these locations could fire off a Spring event, and the instrumentation could listen for those events (assuming the callback runs on the same thread, so the instrumentation has access to the active Span).
Would it be possible for spring-security to add a hook/listener that is triggered with authentication attempt results for inbound requests? This would make writing this type of automatic instrumentation easier.
Would you recommend a different approach?
The text was updated successfully, but these errors were encountered: