Describe the bug The following test works with 3.1, but fails with 401 UNAUTHORIZED with 3.2:

To Reproduce

@SpringBootTest(
    webEnvironment = RANDOM_PORT,
    classes = [Application::class],
    properties = ["spring.main.allow-bean-definition-overriding=true"]
)
@TestConstructor(autowireMode = ALL)
@WithMockUser(authorities = [ROLE_USER])
class HandlerIntegrationTest(
    @MockkBean
    private val searcher: Searcher,
    private val client: WebTestClient,
) {
    @Test
    fun search() {
        val searchResponse = SearchResponse(
            result = listOf(),
            page = 1,
            pageSize = 20,
            total = 0,
            filterOptions = FilterOptions(setOf(), setOf()),
            sort = setOf(),
            descending = listOf(false),
        )
        coEvery { searcher.search(any()) } returns searchResponse
        client.get()
            .uri { it.path("$ENDPOINT/search").build() }
            .exchange()
            .expectStatus()
            .isOk
            .expectBody<SearchResponse>()
            .consumeWith {
                assertThat(it.responseBody).isEqualTo(searchResponse)
            }
    }
}

A custom MapReactiveUserDetailsService has been in place and it looks like this:

    @Bean
    @ConditionalOnProperty(value = ["spring.security.user.passwordGenerated"], matchIfMissing = true, havingValue = "false")
    fun userDetailsService(): MapReactiveUserDetailsService {
        val actuatorUser = User
            .withUsername(securityProperties.user.name)
            .password("{noop}${securityProperties.user.password}")
            .authorities(AUTHORITY_ACTUATOR, AUTHORITY_ACCESS_MONITORING, AUTHORITY_ACCESS_INTERNAL_API).build()

        val monitoringUser = User
            .withUsername(monitoringProperties.username)
            .password("{noop}${monitoringProperties.password}")
            .authorities(AUTHORITY_ACCESS_MONITORING)
            .build()

        return MapReactiveUserDetailsService(actuatorUser, monitoringUser)
    }

Expected behavior The test works

Sample Currently we have tried in 3 different projects with different services always with this same result, thus this might not be an isolated case, but rather a major issue, thus hopefully you can easily identify the cause.

Comment From: RomanKosovnenko

I have the same issue after upgrade to 3.2.0 from Spring-Boot 3.1.5

Comment From: ghost

I have the same issue after upgrade to 3.2.0 from Spring-Boot 3.1.5

Same for me.

Comment From: marcusdacoregio

Hi @andrashatvani, thanks for the report.

Is it possible to provide a minimal, reproducible sample? Or if @RomanKosovnenko and @frederikmartin1337 could provide one, it would be of great value.

Comment From: credmond-git

We are facing a similar issue with webflux and spring security. It seems like in Spring Boot 3.2 we get this message

2023-12-04 10:16:02.207 DEBUG [     parallel-1] a.DelegatingReactiveAuthorizationManager : Checking authorization on '/secureGreeting/admin' using org.springframework.security.config.web.server.ServerHttpSecurity$AuthorizeExchangeSpec$Access$$Lambda$1567/0x000001783ba35570@11c3f649 []
2023-12-04 10:16:02.211 DEBUG [     parallel-1] o.s.s.w.s.a.AuthorizationWebFilter       : Authorization successful []
2023-12-04 10:16:02.449 DEBUG [ctor-http-nio-4] ebSessionServerSecurityContextRepository : No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@6ee73ec4' []
2023-12-04 10:16:02.500 DEBUG [ctor-http-nio-4] ebSessionServerSecurityContextRepository : No SecurityContext found in WebSession: 'org.springframework.web.server.session.InMemoryWebSessionStore$InMemoryWebSession@6ee73ec4' []
2023-12-04 10:16:02.500 DEBUG [ctor-http-nio-4] DelegatingServerAuthenticationEntryPoint : Trying to match using org.springframework.security.config.web.server.ServerHttpSecurity$HttpBasicSpec$$Lambda$1570/0x000001783ba36000@5207bcd6 []
2023-12-04 10:16:02.503 DEBUG [ctor-http-nio-4] DelegatingServerAuthenticationEntryPoint : No match found. Using default entry point org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint@7355b4d8 []

that we did not get in Spring Boot 3.1

2023-12-04 10:13:48.357 DEBUG [     parallel-1] a.DelegatingReactiveAuthorizationManager : Checking authorization on '/secureGreeting/admin' using org.springframework.security.config.web.server.ServerHttpSecurity$AuthorizeExchangeSpec$Access$$Lambda$1543/0x000002da2ba06690@7924cf9 []
2023-12-04 10:13:48.359 DEBUG [     parallel-1] o.s.s.w.s.a.AuthorizationWebFilter       : Authorization successful []
2023-12-04 10:13:48.522  INFO [ctor-http-nio-4] c.e.c.s.c.RoleGreetingController         : adminUser 47rtixo2qy24p40i6ggv3cve9 []

I tried to create a minimal report but was not able to reproduce it.

It seems like somewhere along the way it loses its security context. I dont know if it is related but when debugging i can see in most places the below callstack that populates the security context.

<init>:75, Context4 (reactor.util.context)
put:69, Context3 (reactor.util.context)
currentContext:104, ReactorContextTestExecutionListener$DelegateTestExecutionListener$SecuritySubContext (org.springframework.security.test.context.support)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
currentContext:33, InnerOperator (reactor.core.publisher)
<init>:78, FluxFilterFuseable$FilterFuseableSubscriber (reactor.core.publisher)
subscribeOrReturn:47, MonoFilterFuseable (reactor.core.publisher)
subscribe:63, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribeNext:264, MonoIgnoreThen$ThenIgnoreMain (reactor.core.publisher)
subscribe:51, MonoIgnoreThen (reactor.core.publisher)
subscribe:4512, Mono (reactor.core.publisher)
onComplete:82, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onNext:155, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.filter] filter:112, AuthenticationWebFilter (org.springframework.security.web.server.authentication)
onNext:113, FluxFilter$FilterSubscriber (reactor.core.publisher)
[Mono.just] match:83, ServerWebExchangeMatcher$MatchResult (org.springframework.security.web.server.util.matcher)
request:2571, Operators$ScalarSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:186, FluxFilter$FilterSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:194, MonoFlatMap$FlatMapMain (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
set:2367, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
onSubscribe:2241, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:117, MonoFlatMap$FlatMapMain (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:85, FluxFilter$FilterSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:55, MonoJust (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:55, MonoDeferContextual (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onNext:165, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.map] filter:62, WebFilterChainProxy (org.springframework.security.web.server)
onNext:129, FluxMapFuseable$MapFuseableSubscriber (reactor.core.publisher)
[Mono.flatMap] filter:61, WebFilterChainProxy (org.springframework.security.web.server)
secondComplete:245, MonoFlatMap$FlatMapMain (reactor.core.publisher)
onNext:305, MonoFlatMap$FlatMapInner (reactor.core.publisher)
[Flux.collectList] lambda$filter$2:61, WebFilterChainProxy (org.springframework.security.web.server)
completePossiblyEmpty:2097, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
onComplete:118, MonoCollectList$MonoCollectListSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
fastPath:424, FluxIterable$IterableSubscription (reactor.core.publisher)
request:291, FluxIterable$IterableSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:2067, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:291, MonoFlatMap$FlatMapInner (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:2051, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:201, FluxIterable (reactor.core.publisher)
subscribe:83, FluxIterable (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onNext:165, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.switchIfEmpty] filter:59, WebFilterChainProxy (org.springframework.security.web.server)
onNext:74, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
[Flux.next] filter:58, WebFilterChainProxy (org.springframework.security.web.server)
onNext:82, MonoNext$NextSubscriber (reactor.core.publisher)
[Flux.filterWhen] filter:57, WebFilterChainProxy (org.springframework.security.web.server)
drain:301, FluxFilterWhen$FluxFilterWhenSubscriber (reactor.core.publisher)
onNext:140, FluxFilterWhen$FluxFilterWhenSubscriber (reactor.core.publisher)
[Flux.fromIterable] filter:56, WebFilterChainProxy (org.springframework.security.web.server)
slowPath:335, FluxIterable$IterableSubscription (reactor.core.publisher)
request:294, FluxIterable$IterableSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:200, FluxFilterWhen$FluxFilterWhenSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:201, FluxIterable (reactor.core.publisher)
subscribe:83, FluxIterable (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribeNext:264, MonoIgnoreThen$ThenIgnoreMain (reactor.core.publisher)
subscribe:51, MonoIgnoreThen (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribeNext:264, MonoIgnoreThen$ThenIgnoreMain (reactor.core.publisher)
subscribe:51, MonoIgnoreThen (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:55, MonoDeferContextual (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onStateChange:1169, HttpServer$HttpServerHandle (reactor.netty.http.server)
onStateChange:710, ReactorNetty$CompositeConnectionObserver (reactor.netty)
onStateChange:481, ServerTransport$ChildObserver (reactor.netty.transport)
onInboundNext:652, HttpServerOperations (reactor.netty.http.server)
channelRead:114, ChannelOperationsHandler (reactor.netty.channel)
invokeChannelRead:444, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:238, HttpTrafficHandler (reactor.netty.http.server)
invokeChannelRead:442, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:436, CombinedChannelDuplexHandler$DelegatingChannelHandlerContext (io.netty.channel)
fireChannelRead:346, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:318, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:251, CombinedChannelDuplexHandler (io.netty.channel)
invokeChannelRead:442, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1410, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:440, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:919, DefaultChannelPipeline (io.netty.channel)
read:166, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:788, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:724, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:650, NioEventLoop (io.netty.channel.nio)
run:562, NioEventLoop (io.netty.channel.nio)
run:997, SingleThreadEventExecutor$4 (io.netty.util.concurrent)
run:74, ThreadExecutorMap$2 (io.netty.util.internal)
run:30, FastThreadLocalRunnable (io.netty.util.concurrent)
run:840, Thread (java.lang)

But here it is not populating the security context and the context mono is empty. After this it fails.

<init>:75, Context4 (reactor.util.context)
put:90, Context4 (reactor.util.context)
lambda$wrap$5:565, ObservationWebFilterChainDecorator$WebFilterObservation$SimpleWebFilterObservation (org.springframework.security.web.server)
apply:-1, ObservationWebFilterChainDecorator$WebFilterObservation$SimpleWebFilterObservation$$Lambda$3062/0x0000015f49ecd670 (org.springframework.security.web.server)
subscribeOrReturn:38, MonoContextWrite (reactor.core.publisher)
subscribe:63, InternalMonoOperator (reactor.core.publisher)
subscribe:55, MonoDeferContextual (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:4512, Mono (reactor.core.publisher)
onComplete:82, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onComplete:299, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onComplete:299, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onNext:155, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.switchIfEmpty] verify:53, ReactiveAuthorizationManager (org.springframework.security.authorization)
onNext:74, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
[Mono.filter] verify:52, ReactiveAuthorizationManager (org.springframework.security.authorization)
onNext:118, FluxFilterFuseable$FilterFuseableSubscriber (reactor.core.publisher)
[Mono.deferContextual] check:56, ObservationReactiveAuthorizationManager (org.springframework.security.authorization)
[Mono.doOnError] lambda$check$4:66, ObservationReactiveAuthorizationManager (org.springframework.security.authorization)
onNext:180, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
[Mono.doOnCancel] lambda$check$4:66, ObservationReactiveAuthorizationManager (org.springframework.security.authorization)
onNext:503, FluxPeekFuseable$PeekFuseableConditionalSubscriber (reactor.core.publisher)
[Mono.doOnSuccess] lambda$check$4:60, ObservationReactiveAuthorizationManager (org.springframework.security.authorization)
onNext:180, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
[Mono.defaultIfEmpty] check:65, DelegatingReactiveAuthorizationManager (org.springframework.security.web.server.authorization)
onNext:122, FluxDefaultIfEmpty$DefaultIfEmptySubscriber (reactor.core.publisher)
[Flux.next] check:64, DelegatingReactiveAuthorizationManager (org.springframework.security.web.server.authorization)
onNext:82, MonoNext$NextSubscriber (reactor.core.publisher)
[Flux.concatMap] check:54, DelegatingReactiveAuthorizationManager (org.springframework.security.web.server.authorization)
innerNext:258, FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber (reactor.core.publisher)
onNext:863, FluxConcatMap$ConcatMapInner (reactor.core.publisher)
[Mono.flatMap] lambda$check$2:58, DelegatingReactiveAuthorizationManager (org.springframework.security.web.server.authorization)
onNext:158, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.map] lambda$check$2:57, DelegatingReactiveAuthorizationManager (org.springframework.security.web.server.authorization)
onNext:129, FluxMapFuseable$MapFuseableSubscriber (reactor.core.publisher)
[Mono.filter] lambda$check$2:56, DelegatingReactiveAuthorizationManager (org.springframework.security.web.server.authorization)
onNext:113, FluxFilter$FilterSubscriber (reactor.core.publisher)
[Mono.just] match:83, ServerWebExchangeMatcher$MatchResult (org.springframework.security.web.server.util.matcher)
request:2571, Operators$ScalarSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:186, FluxFilter$FilterSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:171, FluxMapFuseable$MapFuseableSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:194, MonoFlatMap$FlatMapMain (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:2331, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
request:338, FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:108, MonoNext$NextSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:98, FluxDefaultIfEmpty$DefaultIfEmptySubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:139, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:437, FluxPeekFuseable$PeekFuseableConditionalSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:139, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:191, FluxFilterFuseable$FilterFuseableSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
set:2367, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
onSubscribe:2241, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:87, FluxFilterFuseable$FilterFuseableSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:152, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:471, FluxPeekFuseable$PeekFuseableConditionalSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:152, MonoPeekTerminal$MonoTerminalPeekSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:2051, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:70, MonoNext$NextSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:164, FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:201, FluxIterable (reactor.core.publisher)
subscribe:83, FluxIterable (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:55, MonoDeferContextual (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onNext:165, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.defaultIfEmpty] filter:40, ServerRequestCacheWebFilter (org.springframework.security.web.server.savedrequest)
completePossiblyEmpty:2097, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
onComplete:134, FluxDefaultIfEmpty$DefaultIfEmptySubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onComplete:152, FluxMapFuseable$MapFuseableSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onComplete:152, FluxMapFuseable$MapFuseableSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onComplete:171, FluxFilterFuseable$FilterFuseableSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onComplete:350, FluxMapFuseable$MapFuseableConditionalSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
complete:1866, Operators$MonoSubscriber (reactor.core.publisher)
subscribeOrReturn:151, MonoCacheTime (reactor.core.publisher)
subscribe:63, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribeNext:264, MonoIgnoreThen$ThenIgnoreMain (reactor.core.publisher)
subscribe:51, MonoIgnoreThen (reactor.core.publisher)
subscribe:4512, Mono (reactor.core.publisher)
onComplete:82, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onNext:155, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.filter] filter:112, AuthenticationWebFilter (org.springframework.security.web.server.authentication)
onNext:113, FluxFilter$FilterSubscriber (reactor.core.publisher)
[Mono.just] match:83, ServerWebExchangeMatcher$MatchResult (org.springframework.security.web.server.util.matcher)
request:2571, Operators$ScalarSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:186, FluxFilter$FilterSubscriber (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:194, MonoFlatMap$FlatMapMain (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
set:2367, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
onSubscribe:2241, Operators$MultiSubscriptionSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:117, MonoFlatMap$FlatMapMain (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:85, FluxFilter$FilterSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:55, MonoJust (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:55, MonoDeferContextual (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onNext:165, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.map] filter:62, WebFilterChainProxy (org.springframework.security.web.server)
onNext:129, FluxMapFuseable$MapFuseableSubscriber (reactor.core.publisher)
[Mono.flatMap] filter:61, WebFilterChainProxy (org.springframework.security.web.server)
secondComplete:245, MonoFlatMap$FlatMapMain (reactor.core.publisher)
onNext:305, MonoFlatMap$FlatMapInner (reactor.core.publisher)
[Flux.collectList] lambda$filter$2:61, WebFilterChainProxy (org.springframework.security.web.server)
completePossiblyEmpty:2097, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
onComplete:118, MonoCollectList$MonoCollectListSubscriber (reactor.core.publisher)
onComplete:549, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
fastPath:424, FluxIterable$IterableSubscription (reactor.core.publisher)
request:291, FluxIterable$IterableSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
request:2067, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:291, MonoFlatMap$FlatMapInner (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:2051, Operators$BaseFluxToMonoOperator (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:201, FluxIterable (reactor.core.publisher)
subscribe:83, FluxIterable (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onNext:165, MonoFlatMap$FlatMapMain (reactor.core.publisher)
[Mono.switchIfEmpty] filter:59, WebFilterChainProxy (org.springframework.security.web.server)
onNext:74, FluxSwitchIfEmpty$SwitchIfEmptySubscriber (reactor.core.publisher)
[Flux.next] filter:58, WebFilterChainProxy (org.springframework.security.web.server)
onNext:82, MonoNext$NextSubscriber (reactor.core.publisher)
[Flux.filterWhen] filter:57, WebFilterChainProxy (org.springframework.security.web.server)
drain:301, FluxFilterWhen$FluxFilterWhenSubscriber (reactor.core.publisher)
onNext:140, FluxFilterWhen$FluxFilterWhenSubscriber (reactor.core.publisher)
[Flux.fromIterable] filter:56, WebFilterChainProxy (org.springframework.security.web.server)
slowPath:335, FluxIterable$IterableSubscription (reactor.core.publisher)
request:294, FluxIterable$IterableSubscription (reactor.core.publisher)
request:649, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
onSubscribe:200, FluxFilterWhen$FluxFilterWhenSubscriber (reactor.core.publisher)
onSubscribe:633, FluxOnAssembly$OnAssemblySubscriber (reactor.core.publisher)
subscribe:201, FluxIterable (reactor.core.publisher)
subscribe:83, FluxIterable (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:53, MonoDefer (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribeNext:264, MonoIgnoreThen$ThenIgnoreMain (reactor.core.publisher)
subscribe:51, MonoIgnoreThen (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribeNext:264, MonoIgnoreThen$ThenIgnoreMain (reactor.core.publisher)
subscribe:51, MonoIgnoreThen (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
subscribe:55, MonoDeferContextual (reactor.core.publisher)
subscribe:76, InternalMonoOperator (reactor.core.publisher)
onStateChange:1169, HttpServer$HttpServerHandle (reactor.netty.http.server)
onStateChange:710, ReactorNetty$CompositeConnectionObserver (reactor.netty)
onStateChange:481, ServerTransport$ChildObserver (reactor.netty.transport)
onInboundNext:652, HttpServerOperations (reactor.netty.http.server)
channelRead:114, ChannelOperationsHandler (reactor.netty.channel)
invokeChannelRead:444, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:238, HttpTrafficHandler (reactor.netty.http.server)
invokeChannelRead:442, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:436, CombinedChannelDuplexHandler$DelegatingChannelHandlerContext (io.netty.channel)
fireChannelRead:346, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:318, ByteToMessageDecoder (io.netty.handler.codec)
channelRead:251, CombinedChannelDuplexHandler (io.netty.channel)
invokeChannelRead:442, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:412, AbstractChannelHandlerContext (io.netty.channel)
channelRead:1410, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeChannelRead:440, AbstractChannelHandlerContext (io.netty.channel)
invokeChannelRead:420, AbstractChannelHandlerContext (io.netty.channel)
fireChannelRead:919, DefaultChannelPipeline (io.netty.channel)
read:166, AbstractNioByteChannel$NioByteUnsafe (io.netty.channel.nio)
processSelectedKey:788, NioEventLoop (io.netty.channel.nio)
processSelectedKeysOptimized:724, NioEventLoop (io.netty.channel.nio)
processSelectedKeys:650, NioEventLoop (io.netty.channel.nio)
run:562, NioEventLoop (io.netty.channel.nio)
run:997, SingleThreadEventExecutor$4 (io.netty.util.concurrent)
run:74, ThreadExecutorMap$2 (io.netty.util.internal)
run:30, FastThreadLocalRunnable (io.netty.util.concurrent)
run:840, Thread (java.lang)

In my minimal repo when it hits the lambda$wrap$5:565, ObservationWebFilterChainDecorator$WebFilterObservation$SimpleWebFilterObservation (org.springframework.security.web.server) the security's context is there, in my real app it is empty.

Comment From: marcusdacoregio

Hi, everyone. I've created a minimal sample but I had no success reproducing the problem. Can someone apply the needed changes to make the problem reproducible?

Comment From: alex-arana

I had a similar problem running tests in my Spring Webflux application which stopped working after upgrading from 3.1.5 to 3.2.0. I tracked down the problem to the following condition which was added to org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration (ecc6707):

@ConditionalOnMissingClass({ "org.springframework.security.oauth2.client.registration.ClientRegistrationRepository",
        "org.springframework.security.oauth2.server.resource.introspection.ReactiveOpaqueTokenIntrospector" })

In the application properties for my tests I DO configure an OAuth2 client registration repository purely for the purposes of establishing client connections to external APIs.

As a workaround, I added the missing MapReactiveUserDetailsService bean to my test Configuration and everything worked as it did before this change:

https://github.com/spring-projects/spring-boot/blob/fc1a5033e829d903fd2e37989918b1ea202508e4/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveUserDetailsServiceAutoConfiguration.java#L78-L83

Comment From: andrashatvani

As a workaround, I added the missing MapReactiveUserDetailsService bean to my test Configuration and everything worked as it did before this change:

@alex-arana Is it different from how I defined my custom bean in the bug description?

Comment From: andrashatvani

@marcusdacoregio I've created another sample project since our basics are so different e.g. I use Maven. You can find it at https://github.com/andrashatvani/sb32sec . Hope it helps.

Comment From: marcusdacoregio

Thanks for the sample @andrashatvani. It took me a while to make it minimal and runnable, but I found some clues about the problem. I changed my sample to reproduce the error.

The error is only triggered when we do http.csrf(ServerHttpSecurity.CsrfSpec::disable), if you comment that line the test works. I am not sure if this is a problem in Spring Security yet because if using Spring Boot 3.1.6 and Spring Security 6.2.0, the problem does not happen. I'll keep you updated with my findings.

Comment From: jesperancinha

Thanks for the sample @andrashatvani. It took me a while to make it minimal and runnable, but I found some clues about the problem. I changed my sample to reproduce the error.

The error is only triggered when we do http.csrf(ServerHttpSecurity.CsrfSpec::disable), if you comment that line the test works. I am not sure if this is a problem in Spring Security yet because if using Spring Boot 3.1.6 and Spring Security 6.2.0, the problem does not happen. I'll keep you updated with my findings.

This happens to me too in one of my projects. I have also solve it like that. I'm also not sure if letting csrf with its default value is ok.

Comment From: marcusdacoregio

Hi, folks. Unfortunately, I haven't found the root cause yet, however, I can provide a simple workaround so you can update your applications:

http.addFilterAt(new TestWebFilter(), SecurityWebFiltersOrder.CSRF);

// workaround for https://github.com/spring-projects/spring-security/issues/14207
static class TestWebFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return Mono.empty().switchIfEmpty(chain.filter(exchange)).then();
    }

}

Some newest finding points out that there is something related to the Reactor Core and I'll talk with someone from their team early next week.

Comment From: andrashatvani

@marcusdacoregio Unfortunately the workaround is not feasible for us as in the project the security configuration needs to remain untouched even in the integration tests.

Comment From: marcusdacoregio

Hi, everyone. Thanks to the help of @chemicL we managed identify a regression that happened in reactor-core 3.6.0. The PR with the fix is available here.

As soon as reactor core 3.6.2 is available, Spring Security will update to it and I may close this issue if the fix is confirmed. Spring Security 6.2.2 is scheduled for Feb 19th, however, when reactor-core is out you can override its dependency version if you want.

Comment From: chemicL

The issue is caused by a regression introduced in reactor-core 3.6.0 and the PR linked above should bring back the previous behaviour.

In the PR I expressed an opinion that the onLastOperatorHook functionality should probably be deprecated. From my understanding, it was added to improve ThreadLocal propagation across Thread boundaries. It might have been added specifically for Spring Cloud Sleuth which performs tracing instrumentation. onLastOperatorHook has less execution points than the onEachOperatorHook to reduce the performance impact, but requires additional hooks to improve the reliability (onScheduleHook + queue wrapper hook) and still has its shortcomings. Starting from reactor-core 3.5.0 we introduced better mechanisms for propagation of ThreadLocal state.

The issue with onLastOperatorHook can be understood better with a blog post series we published on the subject – part 2 discusses this hook.

The latest-and-greatest context propagation features are described in our documentation.

Comment From: andrashatvani

With reactor-core 3.6.2 all tests pass indeed.

Comment From: chemicL

@andrashatvani thanks for checking it so quickly and letting us know :)

Comment From: marcusdacoregio

Closed via https://github.com/reactor/reactor-core/pull/3673