Docs

Setting Up Spring Security

The minimal setup for securing a Vaadin Flow application with Spring Security.

This page describes the minimal setup for securing a Spring Boot application with Spring Security and Vaadin’s built-in security helpers. It takes the following:

  • the Spring Security dependency;

  • a log-in view;

  • a security configuration class that uses VaadinSecurityConfigurer; and

  • an access annotation on each view class and on each layout class, as described in Annotation-Based Access Control. The log-in view is the only exception.

A complete example project is available at github.com/vaadin/flow-crm-tutorial.

Spring Security Dependency

Add the Spring Boot starter for Spring Security to the project:

Source code
pom.xml
<dependencies>
    <!-- other dependencies -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <!-- other dependencies -->
</dependencies>

Log-in View

The log-in view is where navigation access control sends users who aren’t authenticated when they try to open a protected view. The following example uses the Login component. Any view works, as long as it contains an HTML form that sends the user name and password to the login action:

Source code
LoginView.java
@Route(value = "login", autoLayout = false) 1
@PageTitle("Login")
public class LoginView extends VerticalLayout implements BeforeEnterObserver {

    private LoginForm login = new LoginForm();

    public LoginView() {
        addClassName("login-view");
        setSizeFull();

        setJustifyContentMode(JustifyContentMode.CENTER);
        setAlignItems(Alignment.CENTER);

        login.setAction("login"); 2

        add(new H1("Test Application"), login);
    }

    @Override
    public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
        if(beforeEnterEvent.getLocation()
            .getQueryParameters()
            .getParameters()
            .containsKey("error")) {
            login.setError(true); 3
        }
    }
}
  1. Keeps the log-in view out of an automatic layout — a class annotated with @Layout — so that the log-in form isn’t shown inside the main layout of the application.

  2. Sends the credentials to the login action of Spring Security’s form login.

  3. Shows an error message. When the log-in fails, form login redirects back to the log-in view with the error query parameter.

The log-in view doesn’t need an access annotation. Navigation access control always allows navigation to the configured log-in view, and VaadinSecurityConfigurer permits HTTP requests to it.

Security Configuration Class

The security configuration class applies VaadinSecurityConfigurer to the Spring Security filter chain, and registers the log-in view. The class can have any name. This is a minimal implementation:

Source code
SecurityConfiguration.java
@EnableWebSecurity 1
@Configuration
public class SecurityConfiguration {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // Configure your static resources with public access
        http.authorizeHttpRequests(auth -> auth.requestMatchers("/public/**")
            .permitAll());

        // Configure Vaadin's security using VaadinSecurityConfigurer
        http.with(VaadinSecurityConfigurer.vaadin(), configurer -> { 2
            // This is important to register your login view to the
            // navigation access control mechanism:
            configurer.loginView(LoginView.class); 3

            // You can add any possible extra configurations of your own
            // here (the following is just an example):
            // configurer.enableCsrfConfiguration(false);
        });

        return http.build();
    }

    /**
     * Demo UserDetailsManager which only provides two hardcoded
     * in memory users and their roles.
     * NOTE: This shouldn't be used in real world applications.
     */
    @Bean
    public UserDetailsManager userDetailsService() {
        UserDetails user =
                User.withUsername("user")
                        .password("{noop}user")
                        .roles("USER")
                        .build();
        UserDetails admin =
                User.withUsername("admin")
                        .password("{noop}admin")
                        .roles("ADMIN")
                        .build();
        return new InMemoryUserDetailsManager(user, admin);
    }
}
SecurityConfiguration.java
  1. Enables Spring Security’s web security support. Together with @Configuration, it makes Spring pick up the security filter chain defined in the class.

  2. Applies the Vaadin-specific Spring Security configuration.

  3. Registers the log-in view with Spring Security’s form login and with navigation access control.

VaadinSecurityConfigurer handles the Vaadin-related configuration, and enables view access control. For example, it permits access to Vaadin’s static resources, enables CSRF checking while ignoring unnecessary checking for Vaadin internal requests, and configures proper exception handling for Vaadin applications. See Security Configuration for everything that it configures, and for its options.

Warning
Configure Form Login Through the Configurer

Configure form login with loginView() rather than by calling Spring Security’s formLogin() directly. The configurer applies FormLoginConfigurer internally, and at the same time permits Vaadin’s internal requests, ignores them in the CSRF check, installs a Vaadin-aware request cache and success handler, and registers the log-in view with navigation access control.

A hand-written formLogin() configuration does none of that. The internal request that the log-in view itself makes to the server is then treated as an unauthenticated request and redirected back to the log-in view, which produces an endless redirect loop — typically visible as an ERR_TOO_MANY_REDIRECTS page or a "Connection lost" notification instead of a working log-in form.

Warning
Never Use Hard-Coded Credentials in Production
The implementation of the userDetailsService() method is an in-memory implementation for the sake of brevity in this documentation. In a normal application, you can change the Spring Security configuration to use an authentication provider for Lightweight Directory Access Protocol (LDAP), JAAS, and other real-world sources. See the Spring Security authentication documentation to read more about them.

Updated –