Spring Security and @Async (Authenticated Users mixed up)

Solution 1:

I guess MODE_INHERITABLETHREADLOCAL doesn't work correctly with thread pool.

As a possible solution you can try to subclass ThreadPoolTaskExecutor and override its methods to propagate SecurityContext manually, and then declare that executor instead of <task:executor>, something like this:

public void execute(final Runnable r) {
    final Authentication a = SecurityContextHolder.getContext().getAuthentication();

    super.execute(new Runnable() {
        public void run() {
            try {
                SecurityContext ctx = SecurityContextHolder.createEmptyContext();
                ctx.setAuthentication(a);
                SecurityContextHolder.setContext(ctx);
                r.run();
            } finally {
                SecurityContextHolder.clearContext();
            }
        }
    });
}

Solution 2:

I also ran into that problem. It is important to configure the ThreadPoolTaskExecutor correctly using the DelegatingSecurityContextAsyncTaskExecutor. Also it is important to call the initialize() method, otherwise an error is thrown.

// define the TaskExecutor as a bean
@Bean("threadPoolTaskExecutor")
public TaskExecutor getAsyncExecutor() {

  ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  executor.setCorePoolSize(20);
  executor.setMaxPoolSize(1000);
  executor.setWaitForTasksToCompleteOnShutdown(true);
  executor.setThreadNamePrefix("Async-");
  executor.initialize(); // this is important, otherwise an error is thrown
  return new DelegatingSecurityContextAsyncTaskExecutor(executor); // use this special TaskExecuter
}

// the method in your business logic which is called async
@Override
@Async("threadPoolTaskExecutor")
public void yourLogic() {
  [..]
}

Solution 3:

This is just a hint that needs future investigation (I am too tired, but maybe somebody find this useful for future investigation):

Today I stumbled over org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor see GitHub.

it looks like that his designed to delegate the security context so that it is "passed" through the @Async call.

Also have a look at this post: Spring Security 3.2 M1 Highlights, Servlet 3 API Support is sounds like it is strongly related.