Spring Security and Routing

Hello everyone!

I am currently trying to implement basic security into my spring flow home project. My basic security configuration looks like this:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String[] ALLOWED_URLS_REGEX = {
            "/frontend/.*",
            "/VAADIN/.*",
            "/login.*",
            "/error.*"
			//Some more views
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .csrf()
                    .disable()
                .exceptionHandling()
                    .accessDeniedPage("/error")
                .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"))
                .and()
                    .logout()
                        .logoutSuccessUrl("/")
                .and()
                .authorizeRequests()
                    //allow Vaadin URLs and the views without authentication
                    .regexMatchers(ALLOWED_URLS_REGEX)
                        .permitAll()
                    .requestMatchers(this::isFrameworkInternalRequest)
                        .permitAll()
                    .anyRequest().fullyAuthenticated();
    }

The problem is, that this catches all Request URL like http://localhost:8080/login or http://localhost:8080/fooView.

But when navigating, vaadin always requests from http://localhost:8080/?v-r=uidl&v-uiId=1 and puts the navigation targets inside the payload:

csrfToken: "73802cef-c7dc-4f44-9421-60195c5da8fb",…}
	clientId: 13
	csrfToken: "73802cef-c7dc-4f44-9421-60195c5da8fb"
	rpc: [{type: "navigation", location: "targetView", link: 1}]

		0: {type: "navigation", location: "targetView", link: 1}
			link: 1
			location: "targetView"
			type: "navigation"
			syncId: 13

Is there any way to catch the target of the navigation with the help of spring security?

Hi Julian,

I feel very sorry for answering you not before today…

Not sure if you found the solution already, but we now provide a tutorial that explains the details to integrate Vaadin and Spring Security: https://vaadin.com/tutorials/securing-your-app-with-spring-security/setting-up-spring-security
Check the section about resources that needs to be bypassed.

Hi Paul,

I’ve read the tutorial at https://vaadin.com/tutorials/securing-your-app-with-spring-security/setting-up-spring-security but I still have same issue of Julian.

Below my Spring Security configuration:

@SpringBootApplication
public class DemoApplication extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .exceptionHandling()
            .accessDeniedPage("/error")
            .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/oauth2/authorization/cognito"))
            .and().logout().logoutSuccessUrl("/")
            .and().authorizeRequests()
            .requestMatchers(this::isFrameworkInternalRequest).permitAll()
            .anyRequest().fullyAuthenticated()
            .and().oauth2Login();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
			"/VAADIN/**",
			"/favicon.ico",
			"/robots.txt",
			"/manifest.webmanifest",
			"/sw.js",
			"/offline-page.html",
			"/frontend/**",
			"/webjars/**",
			"/frontend-es5/**", 
			"/frontend-es6/**"
		);
    }

    private boolean isFrameworkInternalRequest(HttpServletRequest request) {
        final String parameterValue = request.getParameter(ApplicationConstants.REQUEST_TYPE_PARAMETER);
        return parameterValue != null
                && Stream.of(ServletHelper.RequestType.values())
                .anyMatch(r -> r.getIdentifier().equals(parameterValue));
    }

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

Then I defined a route to a page with a button that takes a message from a bean (inspired from https://github.com/vaadin-learning-center/spring-secured-vaadin/blob/master/src/main/java/org/vaadin/paul/spring/MainView.java) but when I click the button I get “Server connection lost, trying to reconnect” and I see several XHR requests to http://localhost:8080/?v-r=uidl&v-uiId=1 with POST method that takes a 405 error.

Do you have any clue about this issue?

Thanks and regards,

Alessandro

.requestMatchers(this::isFrameworkInternalRequest).permitAll() should allow that request.
I can’t see what’s wrong with your configuration (though I never used oauth2Login). Maybe the order within configure(HttpSecurity http) matters here?

I just found several logs on backend that may cause the issue about the POST request to http://localhost:8080/?v-r=uidl&v-uiId=1:

2020-05-07 12:11:51.747  WARN 8544 --- [nio-8080-exec-9]
 .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
 
2020-05-07 12:11:54.135  WARN 8544 --- [nio-8080-exec-8]
 .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
 
2020-05-07 12:11:54.408  WARN 8544 --- [io-8080-exec-10]
 .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]

How can I fix this issue ?

Are you using the exact code that you linked to? If not, please show your view implementation, and what exactly happens upon button click. Sounds to me like you use a REST service to fetch the message, and use POST method instead of GET for that request.

Hi Kaspar,
thanks you for your help, I forgot the @RestController annotation in the DemoApplication class, I removed it and everything is ok.

Regards,
Alessandro

Once i enable spring security ,its
issue with
http://localhost:8090/?v-r=uidl&v-uiId=0
Request Method: POST
Status Code: 403
Remote Address: [::1]
:8090

How to fix it spring security can you help to code fix