6

When I try to obtain the principal from the security context in a parallel stream, it always returns null when isn't in the main thread.

The following piece of code fails when the user is authenticated:

listOfSomething.parallelStream()
                .foreach(el -> { 
if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() == null){
            throw new RuntimeException();
}});

The documentation says:

Interface defining the minimum security information associated with the current thread of execution.

But, is there any way to do it? It starts in main thread and use ForkJoinPool

Thank you!

Ganchix
  • 315
  • 4
  • 13
  • 4
    This is not a duplicate. In the linked question, OP spawned a thread explicitly, and attempted to access `SecurityContext` from that thread. In such a case, we are dealing with a child thread, and `MODE_INHERITABLETHREADLOCAL` successfully propagates the `SecurityContext`. Here, we are using `parallelStream()` which will use threads from the fork/join pool (implementation dependent) which may not be children of the initiating thread. – Andrew Spencer Mar 26 '18 at 08:19
  • [This answer](https://stackoverflow.com/a/31052486/587365) might be a more helpful pointer. I haven't yet validated it myself for the case of `SecurityContext` propagation during parallel stream operations. – Andrew Spencer Mar 26 '18 at 08:34

1 Answers1

4

It seems that you need to use a different SecurityContextHolder strategy. See https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle/#securitycontextholder-securitycontext-and-authentication-objects for more details on how to change it

artie
  • 622
  • 5
  • 14
  • 1
    Cool! Thank you! The mode that I'm looking for is `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL` – Ganchix Jan 03 '18 at 12:25
  • 10
    *Don't do this!* Security context should not be used in parallel streams. `ParallelStream` uses a commonly shared `ForkJoinPool.commonPool`, and `MODE_INHERITABLETHREADLOCAL ` will result in pretty nasty security issue described here: https://github.com/spring-projects/spring-security/issues/6856. If you desperately need to use a parallel stream, then you need to bind it to a custom ForkJoinPool which is not shared between different application users. See https://stackoverflow.com/questions/21163108/custom-thread-pool-in-java-8-parallel-stream – Yury Kisliak Dec 03 '20 at 00:26