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?
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?
Following the comments on kuhajeyan's answer, it appears you are not properly using CompletableFuture with Spring @Async.
If you launch your tasks by using e.g. CompletableFuture.supplyAsync(Supplier), they will be executed by the common ForkJoinPool and not the one you have configured for @Async. You could use the overloads that take an Executor as argument, but it would not actually benefit from the advantages of @Async.
What you should do, instead, is let Spring handle the task execution, and simply return a completed CompletableFuture like this:
@Async
public CompletableFuture<String> someMethod() {
    // do some computation, but return a completed future
    return CompletableFuture.completedFuture("Hello World!");
}
Spring will then execute your method asynchronously in the configured executor while immediately return a CompletableFuture which will be completed when your method returns.
If you are using Spring 4.2 or above, this is supported out of the box. Otherwise there is a bit of implementation required, but that would be for another question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With