s1moner3d s1moner3d - 1 month ago 7
Java Question

Java Future - Spring Authentication is null into AuditorAware

This is my scenario:

My app has Mongo Auditing enabled, with a custom AuditorAware which gets the current user from the

SecurityContext
. This works well with synchronous methods, and the current auditor is successfully saved, but I can't make it work properly with
@Async
methods.

I have an async method (
CompletableFuture
) that makes some updates on my Mongo Database. When the
AuditorAware.getCurrentAuditor()
is called, no authentication info exists, and I can't get the current auditor (
SecurityContextHolder.getContext().getAuthentication()
returns
null
).

@Override
public User getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

if (authentication == null || !authentication.isAuthenticated()
|| authentication instanceof AnonymousAuthenticationToken) {
log.error("Not authenticated");
return null;
}

[...]

}


I'm using a
DelegatingSecurityContextAsyncTaskExecutor
:

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(200);
executor.initialize();

return new DelegatingSecurityContextAsyncTaskExecutor(executor);
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new ItacaExceptionHandler();
}

}


How can I make it work properly?

Answer

Spring security context is always bound to Threadlocal.

Probabably you may to additionally set MODE_INHERITABLETHREADLOCAL for the security context.

@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
    methodInvokingFactoryBean.setTargetMethod("setStrategyName");
    methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
    return methodInvokingFactoryBean;
}

http://www.ogrigas.eu/spring/2010/04/inherit-spring-security-context-in-child-threads

How to set up Spring Security SecurityContextHolder strategy?

Comments