> Markdown version of [Setting Up Spring Security](https://vaadin.com/docs/next/flow/security/spring/setup). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Setting Up 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`

- an access annotation on each view class and on each layout class, as described in [Annotation-Based Access Control](https://vaadin.com/docs/next/flow/security/access-control/annotations.md). The log-in view is the only exception.

## <a id="spring-security-dependency"></a>Spring Security Dependency

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

`pom.xml`

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

## <a id="log-in-view"></a>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](https://vaadin.com/docs/next/components/login.md) component. Any view works, as long as it contains an HTML form that sends the user name and password to the `login` action:

`LoginView.java`

```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.

## <a id="security-configuration-class"></a>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:

`SecurityConfiguration.java`

**VaadinSecurityConfigurer**

```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);
    }
}
```

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](https://vaadin.com/docs/next/flow/security/spring/security-configuration.md) 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](https://docs.spring.io/spring-security/reference/servlet/authentication/index.html) to read more about them.
