Vaadin 10 -> 14 : Logout with @Push -> relogin redirects to /vaadinServlet

Hi Community,

I have a question puzzling me where I would need some additional eyes to put me on the right track again.

Currently using Vaadin 14, Spring boot and Spring security 2.1.0 (but have tested with Vaadin 10 and 12 as well → same behaviour).

WebSecurityConfig :
	http
		.csrf().disable()
		.authorizeRequests()
		    //.antMatchers("/vaadinServlet/**").permitAll() 
		    //.antMatchers("/vaadinServlet/HEARTBEAT/**").permitAll()
		    //.antMatchers("/").permitAll()
		    .anyRequest().authenticated()
		    .and()
		.formLogin()
		    //.defaultSuccessUrl("/console")
		    .defaultSuccessUrl("/")
		    .permitAll()
		    .and()
		.logout()
		    //.logoutSuccessHandler(logoutSuccessHandler())
		    //.logoutSuccessUrl("/")
		    .permitAll();
		    //.invalidateHttpSession(true)
		    //.deleteCookies("JSESSIONID");

Problem description :
After performing a logout and performing a relogin, the user is always redirected to a vaadinServlet push (blank) page.
Either the user needs to manually change the URL in the address bar (to see the application again) or i need to close the browser session and reopen one to relogin.
If i disable the @Push command, then the logout/login is behaving fine. This behaviour is only reproducible with @Push set on the mainlayout.

Steps to reproduce :

1. Login to the application -> redirected to / with authenticated user
2. Press the logout button -> redirected to /login again 
3. Relogin to the application -> redirected to /vaadinServlet/?v-r=push&v-uiId=0&v-pushId=61d5b1bd-bdfc-467d-8edc-65850b6c1e56&X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=090400fe-2161-4e65-aed2-6b7cf479bf5c&_=1569327047300   with authenticated user

Wanted behaviour :
On second login, just go to the mainpage / and not redirect to /vaadinServlet/?v-r=push…

My very cluttered logout section because i have tried tons of stuff :

// Redirect this page immediately
		SecurityContextHolder.clearContext();
		VaadinService.getCurrentRequest().getWrappedSession().invalidate();
		
		// Hack to turn off PUSH on all UIs first. Doing it this way to try to avoid spurious PUSH sessions reactivating.
		    for( final UI ui : VaadinSession.getCurrent().getUIs() ) {
//			ui.access((Command) new Runnable() {
//			    @Override
//			    public void run() {
//				ui.getPushConfiguration().setPushMode(PushMode.DISABLED);
//			    }
//			});
			
			ui.access(new Command(){
			    @Override
			    public void execute() {
				LOGGER.info(String.format("DISABLE PUSH :  %s", ui.getPage().getClass().toString()));
				ui.getPushConfiguration().setPushMode(PushMode.DISABLED);
			    }

			});
		    }

		    // Force all UIs to be logged off when any UI logs off
		    for( final UI ui : VaadinSession.getCurrent().getUIs() ) {
			ui.access(new Command(){
			    @Override
			    public void execute() {
				LOGGER.info(String.format("SET LOCATION FOR :  %s", ui.getPage().getClass().toString()));
				ui.getPage().setLocation("/");
			    }

			});
//			ui.access((Command) new Runnable() {
//			    @Override
//			    public void run() {
//				if ( ui instanceof EsfVaadinUI ) {
//				    EsfVaadinUI vui = (EsfVaadinUI)ui;
//				    vui.setLogoffUrlNormal();
//				    vui.getPage().setLocation(logoutUrl); // set the logoff page before we close the session
//				}
//			    }
//			});
		    }
		
		
		getUI().get().getPage().executeJs("window.location.href='logout'");
		//getUI().get().getPage().setLocation("/");
		// Close the session
		LOGGER.info(String.format("KOM IK HIER NOG IN SESSION CLOSE ?"));
		getUI().get().getSession().close();
		getUI().get().getPage().setLocation("/");

Questions that I have :

1. Am i supposed to redirect the user request ? Am i supposed to close any PUSH related sessions ?
2. Do I need to execute some commands in some specific order ?
3. Is there somebody willing to explain me in detail the logout logic in relation to Atmosphere ?
4. Should I take another approach ?
5. Is there any documentation out there that i just need to read to find the answer ?

Similar related issues that i found but have not revealed a solution to me :

https://vaadin.com/forum/thread/7885028

https://vaadin.com/forum/thread/15871148/spring-security-vaadin-push

https://vaadin.com/forum/thread/17348774/logout-invalidate-session-causes-session-expired-when-push-is-enabled

Regards,

Jorn

@Leif Åstrand,
During the Vaadin Dev Day in Berlin I mentioned this problem and you mentioned it might have been fixed in the latest release.
I still have the issue with Vaadin 14.0.12.

If I enable @Push on my MainLayout, the logout is not working properly.
At least the logout is working but if I logon in the same browser tab, the user is redirected to a blank /vaadinServlet page and we should manually correct the path in the address bar.

Grts,
Jorn

The suspected underlying issue that I had in mind was https://github.com/vaadin/flow/issues/4071 which was fixed in Flow 2.0.19 last week. This Flow version is not yet part of any Vaadin release (Vaadin 14.0.14 uses Flow 2.0.18).

We are planning to release Vaadin 14.0.15 including this fix today or tomorrow.

…and now it’s out. https://github.com/vaadin/platform/releases/tag/14.0.15

Please note that there’s still some delay before the artefacts are synchronized to Maven Central. You can check https://repo1.maven.org/maven2/com/vaadin/vaadin/14.0.15/ to see whether it’s already out there.

@Leif Åstrand,

With Vaadin 14.0.15 i still have problems doing an immediate login after a logout.

Currently my logout section looks like this :

logoutBtn.addClickListener(listener -> {


            //UI.getCurrent().getInternals().getPushConnection().disconnect();
			// Redirect this page immediately
			//UI.getCurrent().getPage().executeJs("window.location.href='logout'");
			UI.getCurrent().navigate("logout");
			// Close the session
            VaadinSession.getCurrent().getSession().invalidate();
			UI.getCurrent().getSession().close();
            //UI.getCurrent().close();


		});

The logout is working beautifully, but if i perform a relogin without closing the browser, i am always returned to the following URL :
http://localhost:8080/vaadinServlet/?v-r=push&v-uiId=0&v-pushId=bd2c778a-dae7-45be-82c6-2ad984360394&X-Atmosphere-Transport=close&X-Atmosphere-tracking-id=3a6d553a-d176-47af-ae3c-3eec82cb74fe&_=1575910516767

I have read https://github.com/vaadin/flow/issues/4071 extensively and tried the different commands in different order but i cannot get it to work bugfree. Logging in after logout remains a problem.

If I disable @Push on my main layout, than everything starts to work as expected.
Is there an example app with @Push enabled and where logout/login is working fine ?
Could this be related to Spring Boot ?

Most end users will never notice this but it is just ugly knowing it is there.

Grts,
Jorn

It seems like what happens now is that when the push connection is being closed, there is one last XHR sent to confirm that everything has been shut down properly. This request is sent after the session has been expired and it is thus intercepted by Spring Security. The problem is that Spring Security remembers the last request that has been sent and assumes it’s the most appropriate location to redirect to after logging in since it’s actually sent even after the regular navigation event that renders the login page.

We may want to look in to whether there’s any point in sending this request: https://github.com/vaadin/flow/issues/7120

As a workaround in the application, you could try using something like https://stackoverflow.com/questions/34364802/spring-prevent-ajax-call-from-being-target-url-on-authentication to prevent this request from being considered as redirect target after login.

Hallo Leif,

You pointed me in the right direction. Apparently there is a directive in Spring Security to disable the cache completely that can be set in the WebSecurityConfig.

http.requestCache().disable()

Source : https://github.com/spring-projects/spring-security/issues/6102

After disabling the request cache and @Push enabled, logging in after logging out works perfectly as expected.
I still need to test if disabling the request cache has an influence somewhere in my application but at first sight I don’t think so.

Many thanks for your excellent help !!

Regards,
Jorn

Currently using Vaadin 14, Spring boot and Spring security 2.1.0 (but have tested with Vaadin 10 and 12 as well → same behaviour).

I have encountered same issue, depending on https://stackoverflow.com/questions/34364802/spring-prevent-ajax-call-from-being-target-url-on-authentication i made this piece of code as workaround but I can’t guarantee that there is no side effects.

public class CustomRequestCache extends HttpSessionRequestCache { 

   @Override
   public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
       String parameter = request.getParameter("X-Atmosphere-Transport");
       if (parameter == null || !parameter.equalsIgnoreCase("close") ) {
           super.saveRequest(request, response);
       }
   }
}

and then simply set it in WebSecurityConfigurerAdapter

   @Bean
   public RequestCache requestCache() {
       return new CustomRequestCache();
   }

    @Override
   public void configure(HttpSecurity http) throws Exception {
       http.
               requestCache().requestCache(requestCache())

Seems working in my case.

That seems a more granular solution.
Whereas I just disable the http requestcache globally you seem to exclude only the X-Atmosphere-Transport=close from the requestcache which is a better and more detailed solution !