springspring-bootspring-securityvaadinvaadin24

After Spring Boot 3 update: Manually authenticating user not working


I am upgrading an application to Spring Boot 3. We are using a custom authentication framework where we manually set the authentication object after authenticating the user.

After logging the user in, we call SecurityContextHolder.getContext().setAuthentication(authentication);. This has worked in previous Spring Boot/Security versions without issue. However, after the upgrade SecurityContextHolder.getContext().getAuthentication() returns an AnonymousAuthenticationToken and not the Token we use and need to authenticate and authorise users. The odd thing is that the first time the authentication is checked it contains the proper token, but any time I call SecurityContextHolder.getContext().getAuthentication() after that it returns an AnonymousAuthenticationToken.

Has anyone experienced something similar? This is a Vaadin application, if it makes a difference.

I have found the following tips in the spring docs:

For example, the following code: SecurityContextHolder.setContext(securityContext); should be replaced with SecurityContextHolder.setContext(securityContext); securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse);

However, this is not really useful to me, as this is a Vaadin application and I'm not handling any requests myself.


Solution

  • From https://docs.spring.io/spring-security/reference/5.8/migration/servlet/session-management.html#_require_explicit_saving_of_securitycontextrepository

    In Spring Security 6, the default behavior is that the SecurityContextHolderFilter will only read the SecurityContext from SecurityContextRepository and populate it in the SecurityContextHolder. Users now must explicitly save the SecurityContext with the SecurityContextRepository if they want the SecurityContext to persist between requests. This removes ambiguity and improves performance by only requiring writing to the SecurityContextRepository (i.e. HttpSession) when it is necessary.

    Sounds like you should call securityContextRepository.saveContext(securityContext, httpServletRequest, httpServletResponse); just like you mentioned. In a Vaadin application, you can get the request and response using VaadinServletRequest.getCurrent() and VaadinServletResponse.getCurrent()