Mr Baloon
Mr Baloon

Reputation: 2776

How to handle access denied in Vaadin using Spring Security

I have serious problems getting Vaadin and Spring Security (using auth through AD) working well together. I managed to get the authentication bit working "good enough" (with my own handlers), but when I'm trying to get the authorization bit to work - I get into more trouble. Let's break it up and take the way we should handle access denied.

So, of course I tried setting it up the "preferred" way, by simply using Springs "auto" access denied handler, like this: <access-denied-handler error-page="/403"/>, but that yields a message popup from Vaadin saying:

"Failed to load the bootstrap javascript: ./VAADIN/vaadinBootstrap.js"

I also tried my own custom access denied handler. The Overridden handle method is called no less than 20 times and then the browser (FF in this particular case) gives me this message:

"The page isn't redirecting properly Firefox has detected that the server is redirecting the request for this address in a way that will never complete. This problem can sometimes be caused by disabling or refusing to accept cookies."

This is most likely because the user is not authorized to the redirect page, but I set it to: <intercept-url pattern="/#!access_denied_view" access="permitAll" />, I also tried <intercept-url pattern="/accessdenied.jsp" access="permitAll" /> resulting in the above "bootstrap"-error.

What am I doing wrong? Why is even Vaadin invoked in this case??

Edit: Added possible reason for multiple calls to handle-method

Upvotes: 1

Views: 2147

Answers (3)

Alex
Alex

Reputation: 331

You have to allow Vaadin specific paths and disable csrf in spring security. Vaadin has own csrf managment between client and server.

For example spring boot 1.3.0.RC1 java configuration:

http.authorizeRequests().antMatchers("/VAADIN/**", "/PUSH/**", "/UIDL/**", "/vaadinServlet/UIDL/**").permitAll();
http.csrf().disable();

Upvotes: 1

Ezra Nkayamba
Ezra Nkayamba

Reputation: 19

You need to allow (add to antMatchers) all Vaadin specific denied paths. Below is a sample configure method override; am using Spring authentication with Vaadin as main user interface under /home.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
                .antMatchers("/resources/**", "/webjars/**", "/VAADIN/**", "/PUSH/**", "/UIDL/**", "/vaadinServlet/UIDL/**","/vaadinServlet/HEARTBEAT/**", "/registration").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    http.csrf().ignoringAntMatchers("/home**", "/VAADIN/**", "/PUSH/**", "/UIDL/**", "/vaadinServlet/UIDL/**","/vaadinServlet/HEARTBEAT/**");
}

So the same list of Vaadin paths need to be ignored on Spring Csrf

Upvotes: 0

Sven
Sven

Reputation: 952

As Alexander pointed out, Vaadin has its own CSRF features. The Spring Security CSRF is global and it must be turned off completely for all requests. Another option is to create a small request matcher that enables or disables the Spring Security for each request. Then you can still run CSRF support for all requests outside the Vaadin app (such as REST or other pages).

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/", "/support").permitAll()
            .anyRequest().fullyAuthenticated()
            .and().formLogin()
            .and().httpBasic()
            .and().csrf().requireCsrfProtectionMatcher(new RequestMatcher() {

                private RegexRequestMatcher nsdoc = 
                        new RegexRequestMatcher("/open/*", null);

                @Override
                public boolean matches(final HttpServletRequest arg0) {

                    if (nsdoc.matches(arg0)) {
                        return true;
                    } else {
                        return false;
                    }
                }
            });

In this configuration, all requests under the URI / and /support are permitted without login. Everything under the URI /open will be handled by the Spring CSRF features while the rest (like Vaadin) will take care of its own.

Upvotes: 0

Related Questions