Skip to content

Commit

Permalink
fix: fix redirect URL for PUSH with websocket transport (#20666) (CP:…
Browse files Browse the repository at this point in the history
… 24.4) (#20678)

* fix: fix redirect URL for PUSH with websocket transport (#20666)

When PUSH is enabled with websocket transport, the redirect URL to be used
after a successfull login is not correctly computed because it is based
on the PUSH servlet mapping.
This change detects the situation and computes the correct URL.

Fixes #20575

* fix version

---------

Co-authored-by: Marco Collovati <[email protected]>
  • Loading branch information
vaadin-bot and mcollovati authored Dec 11, 2024
1 parent 25b0c3f commit 375e795
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import com.vaadin.flow.router.NotFoundException;
import com.vaadin.flow.router.RouteParameters;
import com.vaadin.flow.router.internal.PathUtil;
import com.vaadin.flow.server.Constants;
import com.vaadin.flow.server.HandlerHelper;
import com.vaadin.flow.server.VaadinRequest;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinServletRequest;
Expand Down Expand Up @@ -369,7 +371,13 @@ protected Predicate<String> getRolesChecker(VaadinRequest request) {
*/
protected String getRequestURL(VaadinRequest vaadinRequest) {
if (vaadinRequest instanceof VaadinServletRequest httpRequest) {
return httpRequest.getRequestURL().toString();
String url = httpRequest.getRequestURL().toString();
if (HandlerHelper.isRequestType(vaadinRequest,
HandlerHelper.RequestType.PUSH)
&& url.endsWith(Constants.PUSH_MAPPING)) {
url = url.substring(0, url.indexOf(Constants.PUSH_MAPPING));
}
return url;
}
return "";
}
Expand Down
1 change: 1 addition & 0 deletions flow-tests/vaadin-spring-tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
<module>test-mvc-without-endpoints</module>

<module>test-spring-security-flow</module>
<module>test-spring-security-flow-websocket</module>
<module>test-spring-security-webicons</module>
<module>test-spring-security-webicons-urlmapping</module>
<module>test-spring-security-flow-contextpath</module>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring-tests</artifactId>
<version>24.4-SNAPSHOT</version>
</parent>
<artifactId>test-spring-security-flow-websocket</artifactId>
<name>Integration tests for Vaadin Spring Security and Flow With Websocket PUSH</name>
<packaging>jar</packaging>
<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>

<dependencies>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-spring</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-dev-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
<groupId>com.vaadin</groupId>
<artifactId>test-spring-security-flow</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>test-spring-security-flow</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<defaultGoal>spring-boot:run</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
</plugins>
</pluginManagement>

<plugins>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>flow-maven-plugin</artifactId>
<version>${project.version}</version>
<configuration>
<forceProductionBuild>true</forceProductionBuild>
</configuration>
<executions>
<execution>
<goals>
<goal>prepare-frontend</goal>
<goal>build-frontend</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=18888
</jvmArguments>
</configuration>
<executions>
<!-- start and stop application when running
integration tests -->
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.vaadin.flow.spring.flowsecuritywebsocket;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application
extends com.vaadin.flow.spring.flowsecurity.Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2000-2024 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.vaadin.flow.spring.flowsecuritywebsocket;

import org.springframework.stereotype.Component;

import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterListener;
import com.vaadin.flow.router.ListenerPriority;
import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;
import com.vaadin.flow.shared.ui.Transport;

@Component
public class PushWebsocketConfigurer implements VaadinServiceInitListener {

private final PushTransportSetter pushTransportSetter = new PushTransportSetter();

@Override
public void serviceInit(ServiceInitEvent event) {

event.getSource().addUIInitListener(uiInitEvent -> {
// Transport cannot be set directly in UI listener because
// BootstrapHandler overrides it with @Push annotation value.
uiInitEvent.getUI().addBeforeEnterListener(pushTransportSetter);
});
}

@ListenerPriority(10)
private static class PushTransportSetter implements BeforeEnterListener {

@Override
public void beforeEnter(BeforeEnterEvent event) {
event.getUI().getPushConfiguration()
.setTransport(Transport.WEBSOCKET);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
server.port=8888
logging.level.org.springframework.security=TRACE
logging.level.org.atmosphere=DEBUG
server.servlet.session.persistent=false
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.vaadin.flow.spring.flowsecuritywebsocket;

import org.junit.Ignore;
import org.junit.Test;

public class AppViewIT extends com.vaadin.flow.spring.flowsecurity.AppViewIT {

@Test
@Ignore("""
With WEBSOCKET transport the WS connection is closed when session
is invalidated, but Flow client attempts a reconnection and
re-enables heartbeat. The heartbeat ping resolves in a 403 HTTP
status code because of session expiration, causing the client-side
session expiration handler to redirect to the timeout page instead
of the logout view, because the logout process is still ongoing.
""")
public void logout_via_doLogin_redirects_to_logout() {
super.logout_via_doLogin_redirects_to_logout();
}
}
1 change: 1 addition & 0 deletions scripts/computeMatrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const moduleWeights = {
'flow-tests/vaadin-spring-tests/test-spring-security-flow': { pos: 5, weight: 3 },
'flow-tests/vaadin-spring-tests/test-spring-security-webicons': { pos: 5, weight: 3 },
'flow-tests/vaadin-spring-tests/test-spring-security-webicons-urlmapping': { pos: 5, weight: 3 },
'flow-tests/vaadin-spring-tests/test-spring-security-flow-websocket': { pos: 5, weight: 3 },
'flow-tests/vaadin-spring-tests/test-spring-security-flow-contextpath': { pos: 5, weight: 3 },
'flow-tests/vaadin-spring-tests/test-spring-security-flow-methodsecurity': { pos: 5, weight: 3 },
'flow-tests/vaadin-spring-tests/test-spring-security-flow-urlmapping': { pos: 5, weight: 3 },
Expand Down

0 comments on commit 375e795

Please sign in to comment.