Skip to content

Logout fails due to invalidated session in WebFlux application #1523

Closed
@vpavic

Description

@vpavic

This appears to be a regression somewhere between Spring WebFlux, Spring Session and Spring Security.

The problem can be reproduced using sample-websession project from this repo (note: requires locally running Redis). Steps to reproduce:

  • login using user/password
  • attempt to logout

This results in:

2019-10-04 21:17:13.645 ERROR 13603 --- [llEventLoop-4-1] a.w.r.e.AbstractErrorWebExceptionHandler : [03b45714] 500 Server Error for HTTP POST "/logout"

java.lang.IllegalStateException: Session was invalidated
	at org.springframework.session.data.redis.ReactiveRedisSessionRepository.lambda$save$1(ReactiveRedisSessionRepository.java:127) ~[spring-session-data-redis-2.2.0.RC1.jar:2.2.0.RC1]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.ui.LoginPageGeneratingWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.csrf.CsrfWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
	|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
	|_ checkpoint ⇢ HTTP POST "/logout" [ExceptionHandlingWebHandler]
Stack trace:
		at org.springframework.session.data.redis.ReactiveRedisSessionRepository.lambda$save$1(ReactiveRedisSessionRepository.java:127) ~[spring-session-data-redis-2.2.0.RC1.jar:2.2.0.RC1]
		at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onNext(FluxUsingWhen.java:355) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:242) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:114) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
		at io.lettuce.core.RedisPublisher$ImmediateSubscriber.onNext(RedisPublisher.java:900) ~[lettuce-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
		at io.lettuce.core.RedisPublisher$RedisSubscription.onNext(RedisPublisher.java:284) ~[lettuce-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
		at io.lettuce.core.RedisPublisher$SubscriptionCommand.complete(RedisPublisher.java:768) ~[lettuce-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
		at io.lettuce.core.protocol.CommandHandler.complete(CommandHandler.java:652) ~[lettuce-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
		at io.lettuce.core.protocol.CommandHandler.decode(CommandHandler.java:612) ~[lettuce-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
		at io.lettuce.core.protocol.CommandHandler.channelRead(CommandHandler.java:563) ~[lettuce-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:794) ~[netty-transport-native-epoll-4.1.39.Final-linux-x86_64.jar:4.1.39.Final]
		at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:424) ~[netty-transport-native-epoll-4.1.39.Final-linux-x86_64.jar:4.1.39.Final]
		at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:326) ~[netty-transport-native-epoll-4.1.39.Final-linux-x86_64.jar:4.1.39.Final]
		at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) ~[netty-common-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.42.Final.jar:4.1.42.Final]
		at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.42.Final.jar:4.1.42.Final]
		at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

If Spring Boot is downgraded to 2.1.9.RELEASE, everything works. It also works when upgraded to 2.2.0.M4, the trouble starts with 2.2.0.M5 onwards.

I've also tried working with 2.1.9.RELEASE and upgrading Framework, Security and Session to current releases individually, but this also works.

Metadata

Metadata

Assignees

Labels

for: external-projectFor an external project and not something we can fix

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions