I’m migrating an application from Spring Boot 2 to Spring Boot 3, and I’ve encountered an issue with security context propagation in asynchronous code.
I have a REST controller method that executes long-running logic asynchronously using CompletableFuture
. Here’s a simplified version of the code:
CompletableFuture.supplyAsync(() -> logic())
.thenApply(it -> {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// some logic
})
.thenApply(it -> {
// more logic
})
.exceptionally(handleError());
On Spring Boot 2, I can successfully retrieve the Authentication object from the SecurityContextHolder
inside the async logic. However, in Spring Boot 3, getAuthentication()
returns null.
In Spring Boot 2 configuration I have a custom executor bean that uses DelegatingSecurityContextAsyncTaskExecutor
, but in Spring Boot 3, I removed this custom executor.
In both versions, I am not explicitly passing the executor when using CompletableFuture.
Why does this behavior change in Spring Boot 3, and what could be the reason for the SecurityContext not being propagated properly in the asynchronous flow?
You need to sign in to view this answers
Leave feedback about this