I was trying to get session cookies working with spring webflux and redis. I implemented a custom logout endpoint, that invalidates the existing WebSession.
Now I ran into the issue, that the session cookie is not deleted, if I set the maxAge property in my application.yaml like this.
server:
reactive:
session:
cookie:
maxAge: 30m
The reason for this lies in the implementation of the expireSession and the initSessionCookie methods.
https://github.com/spring-projects/spring-framework/blob/6548cee20a6df2dca88d205f17478f16599be220/spring-web/src/main/java/org/springframework/web/server/session/CookieWebSessionIdResolver.java#L114
https://github.com/spring-projects/spring-framework/blob/1f1f222b8bd84616ebbcdeaaaf19a8c438f37b11/spring-web/src/main/java/org/springframework/web/server/session/CookieWebSessionIdResolver.java#L129
If we have the properties set like mentioned, then the cookieInitializer in line 129 gets triggered which overwrites the previously set value for maxAge of 0 to the one set in the properties, thus resulting in a session cookie, that has an empty value, but is still valid for the defined duration.
This causes problems, as soon as the user calls an endpoint that is working with the session cookie, the call fails with an IllegalArgumentException saying sessionId must not be empty
In the case of expiring a session the maxAge should always be 0, no matter what was set in the application properties.
I changed the implementation of the expireSession method like this, which causes the correct maxAge to be set in the specific case and the cookie gets removed from the browser.
@Override
public void expireSession(ServerWebExchange exchange) {
ResponseCookie cookie = initSessionCookie(exchange, "", Duration.ZERO)
.mutate()
.maxAge(Duration.ZERO)
.build();
exchange.getResponse().getCookies().set(this.cookieName, cookie);
}
Maybe this or a similar solution could replace the previous one, so that we are still able to define a maxAge for our session cookies and have them invalidated, once we don't need them anymore.
Comment From: seabamirum
I'm also encountering this issue. Might be possible to override CookieWebSessionIdResolver and wire it as a custom bean in the meantime.
Comment From: seabamirum
This worked for me:
@Component
public class CustomCookieWebSessionIdResolver extends CookieWebSessionIdResolver
{
@Override
public void expireSession(ServerWebExchange exchange) {
ResponseCookie.ResponseCookieBuilder cookieBuilder = ResponseCookie.from("SESSION")
.path(exchange.getRequest().getPath().contextPath().value() + "/")
.maxAge(0)
.httpOnly(true);
exchange.getResponse().getCookies().set("SESSION",cookieBuilder.build());
}
}