> Markdown version of [Enabling Security](https://vaadin.com/docs/next/flow/security/enabling-security). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Securing Spring Boot Applications

Vaadin Flow is fully compatible with the most-popular security solutions in the Java ecosystem, including but not limited to Spring Security, Java Authentication and Authorization Service (JAAS), and Apache Shiro.

Although you can choose the security framework you want, Vaadin Flow comes with built-in security helpers that are most conveniently implemented with Spring Security. Using these built-in helpers with Spring Security makes it easier, faster, and safer to secure your Vaadin applications compared to using the Spring Security framework directly — or with any other security framework.

This page focuses on enabling security using the built-in helpers in combination with Spring Boot and Spring Security. For instructions on using the built-in helpers in non-Spring projects, see the [Securing Plain Java Applications](https://vaadin.com/docs/next/flow/security/advanced-topics/securing-plain-java-app.md) documentation page.

## <a id="introduction"></a>Introduction

In a Spring Boot application, Vaadin Flow’s built-in security helpers enable a view-based access control mechanism with minimum Spring Security configuration. This mechanism allows you to secure view flexibly in Vaadin Flow applications, based on different access level annotations. Specifically, the view-based access control mechanism uses the `@AnonymousAllowed`, `@PermitAll`, `@RolesAllowed`, and `@DenyAll` annotations on view classes to define the access control rules.

To enable the mechanism in a Vaadin Flow Spring Boot application without any security, be sure to add the following to your project:

- Login view;

- Spring Security dependencies;

- Log-out capability;

- Security configuration class that uses `VaadinSecurityConfigurer`; and

- One of these annotations on each view class: `@AnonymousAllowed`, `@PermitAll`, or `@RolesAllowed`.

A complete example project, including the source code from this document, is available at [`github.com/vaadin/flow-crm-tutorial`](https://github.com/vaadin/flow-crm-tutorial).

## <a id="log-in-view"></a>Log-in View

A log-in view is a basic requirement of many authentication and authorization mechanisms. It allows you to redirect anonymous users to that page, before allowing them to view any protected resources. The log-in view should always be accessible by anonymous users.

`LoginView.java`

```java
@Route("login")
@PageTitle("Login")
@AnonymousAllowed
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");

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

    @Override
    public void beforeEnter(BeforeEnterEvent beforeEnterEvent) {
        if(beforeEnterEvent.getLocation()
            .getQueryParameters()
            .getParameters()
            .containsKey("error")) {
            login.setError(true);
        }
    }
}
```

This example uses Vaadin’s Login Form component for brevity in this implementation. However, there’s no requirement to use it. Use whatever log-in view you prefer.

## <a id="spring-security-dependencies"></a>Spring Security Dependencies

To enable Spring Security, certain dependencies should be added to the project. Since the examples on this page are based on Spring Boot, you would add the following dependency:

`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-out-capability"></a>Log-Out Capability

To initiate logging out of a web applications, you would typically provide a log-out button. Here is a basic implementation of a log-out button shown on the header of the main layout:

`MainLayout.java`

```java
public class MainLayout extends AppLayout {

    private SecurityService securityService;

    public MainLayout(@Autowired SecurityService securityService) {
        this.securityService = securityService;

        H1 logo = new H1("Vaadin CRM");
        logo.addClassName("logo");
        HorizontalLayout header;
        if (securityService.getAuthenticatedUser() != null) {
            Button logout = new Button("Logout", click ->
                    securityService.logout());
            header = new HorizontalLayout(logo, logout);
        } else {
            header = new HorizontalLayout(logo);
        }

        // Other page components omitted.

        addToNavbar(header);
    }
}
```

The method of getting the authenticated user and logging them out may vary from one application to another. Here’s a basic example of this with the Spring Security API:

`SecurityService.java`

```java
@Component
public class SecurityService {

    private static final String LOGOUT_SUCCESS_URL = "/";

    public UserDetails getAuthenticatedUser() {
        SecurityContext context = SecurityContextHolder.getContext();
        Object principal = context.getAuthentication().getPrincipal();
        if (principal instanceof UserDetails) {
            return (UserDetails) context.getAuthentication().getPrincipal();
        }
        // Anonymous or no authentication.
        return null;
    }

    public void logout() {
        UI.getCurrentOrThrow().getPage().setLocation(LOGOUT_SUCCESS_URL);
        SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
        logoutHandler.logout(
                VaadinServletRequest.getCurrent().getHttpServletRequest(), null,
                null);
    }
}
```

## <a id="security-utilities"></a>Security Utilities

To access authenticated user details and to simplify the handling of logout, Vaadin provides an `AuthenticationContext` component — which is strictly integrated with Spring Security — that can be injected into views and services.

The `AuthenticationContext` by design does not implement `java.io.Serializable`. Vaadin view fields referencing this object must be defined `transient`. The class exposes the following utility methods:

- `isAuthenticated()` checks if a user is currently logged in. The Spring `Anonymous` user is considered not authenticated.

- `getAuthenticatedUser(Class<U> userType)` gets user details. If `userType` doesn’t match the actual user implementation, the method throws a `ClassCastException`.

- `getGrantedRoles()` gets the roles assigned to the user, stripping the role prefix (e.g. `ROLE_USER` is returned as `USER`).

- `hasRole(String role)`, `hasAnyRole(String…​ roles)`, `hasAllRoles(String…​ roles)` check if the user is assigned to given roles. Roles should be provided without role prefix.

- `getGrantedAuthorities()` gets the authorities that have been granted to the user.

- `hasAuthority(String authority)`, `hasAnyAuthority(String…​ authorities)`, `hasAllAuthorities(String…​ authorities)` check if the user has been granted certain authorities.

- `logout` initiates the Spring Security logout process and redirects the user to the configured logout URL.

Here’s an implementation of a log-out button shown on the header of the main layout that uses the `AuthenticationContext` component:

`MainLayout.java`

```java
public class MainLayout extends AppLayout {

    private final transient AuthenticationContext authContext;

    public MainLayout(AuthenticationContext authContext) {
        this.authContext = authContext;

        H1 logo = new H1("Vaadin CRM");
        logo.addClassName("logo");
        HorizontalLayout
        header =
        authContext.getAuthenticatedUser(UserDetails.class)
                .map(user -> {
                    Button logout = new Button("Logout", click ->
                            this.authContext.logout());
                    Span loggedUser = new Span("Welcome " + user.getUsername());
                    return new HorizontalLayout(logo, loggedUser, logout);
                }).orElseGet(() -> new HorizontalLayout(logo));

        // Other page components omitted.

        addToNavbar(header);
    }
}
```

The same component also covers programmatic access checks elsewhere in the application, such as deciding whether to render a navigation item or to enable an action. Roles are given without the role prefix, which `AuthenticationContext` adds when comparing against the granted authorities (see [Roles & the Role Prefix](#role-prefix)). An application migrating from a custom security mechanism therefore doesn’t need a security utility class of its own:

```java
SideNav nav = new SideNav();
nav.addItem(new SideNavItem("Dashboard", DashboardView.class));
if (authContext.hasRole("ADMIN")) { // Not "ROLE_ADMIN".
    nav.addItem(new SideNavItem("Administration", AdminView.class));
}
```

Hiding a navigation item is a usability measure, not a security measure. The view it points to still needs its own access annotation, since a user can navigate there by entering the URL directly.

## <a id="security-configuration-class"></a>Security Configuration Class

The next step is to have a Spring Security configuration class that uses `VaadinSecurityConfigurer`. There’s no convention for naming this class, so here it’s named `SecurityConfiguration`. However, take care with Spring Security annotations.

This is a minimal implementation of such a class:

`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 -> { // (3)
            // This is important to register your login view to the
            // navigation access control mechanism:
            configurer.loginView(LoginView.class); // (4)

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

Notice the including of `@EnableWebSecurity` and `@Configuration` annotations on top of the above class. As their names imply, they instruct Spring to enable its security features.

`VaadinSecurityConfigurer` is a helper class that configures the common Vaadin-related Spring Security settings. By using it, the view-based access control mechanism is enabled automatically, and no further configuration is needed.

The `VaadinSecurityConfigurer` handles all of the Vaadin-related configuration. For example, it ignores static resources, enables `CSRF` checking while ignoring unnecessary checking for Vaadin internal requests, and configures proper exception handling for Vaadin applications.

The log-in view can be configured via the provided `loginView()` method on the configurer.

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

> **Note: Blocked Sub-Resources Answer With 401**
>
> With a log-in view configured, an unauthorized request that the browser makes for a sub-resource — a stylesheet, script, image, font, or web app manifest — is answered with `401 Unauthorized` rather than redirected to the log-in view, which such a request can’t render. The browser then reports the resource that was blocked, instead of failing in a redirect loop. Permit the path in the security configuration to serve the resource; see [Spring Security and StyleSheet](https://vaadin.com/docs/next/upgrading.md#spring-security-and-stylesheet). (since V25.3)

> **Warning: Never Use Hard-Coded Credentials in Production**
>
> The implementation of the `userDetailsService()` method is just 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 [Spring Security authentication providers](https://dzone.com/articles/flow/spring-security-authentication) to read more about them.

The most important configuration in the previous example is the call to `configurer.loginView(LoginView.class)`. This is how the view-based access control mechanism knows where to redirect users when they try to navigate to a protected view.

The log-in view should always be accessible by anonymous users, so it should have the `@AnonymousAllowed` annotation. This is especially important when using the variant of the `loginView` method where you provide the route path — although this signature is meant to be used with [Hilla](https://vaadin.com/hilla) views, not with Flow views.

For additional information about navigation access control, consult the [related documentation](https://vaadin.com/docs/next/flow/security/advanced-topics/navigation-access-control.md).

> **Note: Component-Based Security Configuration**
>
> Spring Security 5.7.0 deprecates the `WebSecurityConfigurerAdapter`. Migrate to a component-based security configuration.

The component-based security configuration shown in the `SecurityConfiguration` example above is the recommended approach. Read more about [updating from WebSecurityConfigurerAdapter to component-based security configuration](https://spring.io/blog/2022/02/21/spring-security-without-the-websecurityconfigureradapter).

Once the `LoginView` is ready, and you’ve set it as the log-in view in the security configuration, you’re ready to move ahead and see how the security annotations work on the views.

## <a id="annotating-the-view-classes"></a>Annotating View Classes

Before providing some usage examples of access annotations, it would be good to have a closer look at the annotations and their meaning when applied to a view:

- `@AnonymousAllowed` permits anyone to navigate to a view without any authentication or authorization.

- `@PermitAll` allows any authenticated user to navigate to a view.

- `@RolesAllowed` grants access to users having the roles specified in the annotation value.

- `@DenyAll` disallows everyone from navigating to a view. This is the default; if a view isn’t annotated, the `@DenyAll` logic is applied.

When using `VaadinSecurityConfigurer`, Vaadin’s `SpringSecurityAutoConfiguration` comes into play and enables the navigation access control mechanism with view-based security. Therefore, none of the views are accessible until one of these annotations is applied to them — except `@DenyAll`.

Below is an example using `@AnonymousAllowed` to enable all users to navigate to this view:

```java
@Route(value = "", layout = MainView.class)
@PageTitle("Public View")
@AnonymousAllowed
public class PublicView extends VerticalLayout {
    // ...
}
```

This next example is using `@PermitAll` to allow only authenticated users — with any role — to navigate to this view:

```java
@Route(value = "private", layout = MainView.class)
@PageTitle("Private View")
@PermitAll
public class PrivateView extends VerticalLayout {
    // ...
}
```

This example is using `@RolesAllowed` to enable only the users with `ADMIN` role to navigate to this view:

```java
@Route(value = "admin", layout = MainView.class)
@PageTitle("Admin View")
@RolesAllowed("ADMIN") // <- Should match one of the user's roles (case-sensitive)
public class AdminView extends VerticalLayout {
    // ...
}
```

### <a id="role-prefix"></a>Roles & the Role Prefix

Spring Security distinguishes between *authorities*, which are arbitrary strings, and *roles*, which are authorities carrying a prefix. The default prefix is `ROLE_`. Role names in `@RolesAllowed` are given without the prefix, and the prefix is added when the granted authorities are checked. So `@RolesAllowed("ADMIN")` matches the granted authority `ROLE_ADMIN`.

This matters when writing a custom `UserDetailsService` or authentication provider, since the authorities have to be created with the prefix included:

```java
List<GrantedAuthority> authorities = user.getRoles().stream()
        .map(role -> new SimpleGrantedAuthority("ROLE_" + role))
        .collect(Collectors.toList());
```

The `roles()` builder method of Spring’s `User` class adds the prefix for you, whereas `authorities()` doesn’t. That’s why the examples on this page use `User.withUsername("admin").roles("ADMIN")` to grant the `ROLE_ADMIN` authority.

> **Warning: Missing Prefixes Fail Silently**
>
> If the authority is stored as `ADMIN` instead of `ROLE_ADMIN`, no error is reported. The role check never matches: views annotated with `@RolesAllowed("ADMIN")` become inaccessible, and any menu item shown conditionally on that role disappears. If a role check doesn’t behave as expected, log `AuthenticationContext.getGrantedAuthorities()` and confirm that the authorities carry the prefix.

To use a prefix other than `ROLE_`, or none at all, define a `GrantedAuthorityDefaults` bean. Vaadin picks up the configured prefix and applies it to the access annotations and to the role-checking methods of `AuthenticationContext`:

```java
@Bean
static GrantedAuthorityDefaults grantedAuthorityDefaults() {
    return new GrantedAuthorityDefaults(""); // No prefix.
}
```

### <a id="annotation-inheritance-overrides"></a>Annotation Inheritance & Overrides

As shown in the example here, the security annotations are inherited from the closest parent class that has them. Annotating a child class overrides any inherited annotations. Interfaces aren’t checked for annotations, only classes.

```java
@RolesAllowed("ADMIN")
public abstract class AbstractAdminView extends VerticalLayout {
    // ...
}

@Route(value = "user-listing", layout = MainView.class)
@PageTitle("User Listing")
public class UserListingView extends AbstractAdminView {
    // ...
}
```

Security annotations on parent layouts are also checked. This applies to auto-layouts (i.e., classes annotated with `@Layout`), to parent layouts set via the `layout` attribute in `@Route`, and to layouts defined with `@ParentLayout`. If a parent layout lacks an access annotation, the default `@DenyAll` logic is applied to the layout, and access to views within it is denied. Both the layout and the view must independently grant access for navigation to succeed. If multiple annotations are specified on a single view class, the following rules are applied:

- `DenyAll` overrides other annotations;

- `AnonymousAllowed` overrides `RolesAllowed`, as well as `PermitAll`; and

- `RolesAllowed` overrides `PermitAll`.

Specifying more than one of the above access annotations on a view class isn’t recommended. Besides the fact that there’s probably no logical reason to do so, it would be confusing.

## <a id="authenticated-user-information"></a>Authenticated User Information

To access the authenticated user’s information (e.g., name, email and roles), Vaadin Flow provides the `AuthenticationContext` class that can be used to retrieve this information. `AuthenticationContext` is a Spring bean that can be injected as a view constructor argument. And `AuthenticationContext` can be useful for rendering the UI differently based on the user’s roles.

The following example shows how to use `AuthenticationContext` to retrieve the authenticated user’s information and render a button only if the user has the `ADMIN` role:

```java
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.H2;;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.spring.security.AuthenticationContext;
import org.springframework.security.core.userdetails.UserDetails;

@Route(value = "my-view")
@AnonymousAllowed
public class MyView extends VerticalLayout {

    public MyView(AuthenticationContext authContext) {

        add(new H2("Everyone can see this"));

        // Ensure that the class used by getAuthenticatedUser() matches the object type created
        // by the authentication providers used in Spring Security.
        authContext.getAuthenticatedUser(UserDetails.class).ifPresent(user -> {
            boolean isAdmin = user.getAuthorities().stream()
                    .anyMatch(grantedAuthority -> "ROLE_ADMIN".equals(grantedAuthority.getAuthority()));
            if (isAdmin) {
                add(new Button("Admin button"));
            } else {
                add(new H2("You are not an admin"));
            }
        });
    }
}
```

## <a id="error-messages-for-unauthorized-views"></a>Error Messages for Unauthorized Views

If the user is already authenticated and tries to navigate to a view for which they don’t have permission, an error message is displayed. The message depends on the application mode.

In development mode, Vaadin shows the `RouteAccessDeniedError` view, which shows an *Access Denied* message with a list of available routes. In production mode, Vaadin shows the `RouteAccessDeniedError` view, which shows by default a message that reads, *Could Not Navigate to 'RequestedRouteName'*. As a security precaution, the message won’t say whether the navigation target exists.

The `RouteAccessDeniedError` is not by default a view, but a reroute to the `RouteNotFoundError` view for better backwards compatibility.

## <a id="custom-error-messages-for-unauthorized-views"></a>Custom Error Messages for Unauthorized Views

Vaadin shows by default the `RouteAccessDeniedError` view for unauthorized views. This can be customized in the following ways:

- Providing custom implementation by overriding `RouteAccessDeniedError` class;

- Providing custom implementation by implementing `HasErrorParameter<AccessDeniedException>` interface; and

- Rerouting to a different error type with `@AccessDeniedErrorRouter` annotation.

The following is one example of this approach, using a custom error by overriding a class:

```java
public class CustomAccessDeniedError extends RouteAccessDeniedError {
    @Override
    public int setErrorParameter(BeforeEnterEvent event,
            ErrorParameter<AccessDeniedException> parameter) {
        getElement().setText("Nothing to see here, please move on");
        return HttpStatusCode.FORBIDDEN.getCode();
    }
}
```

This next example provides a custom error by implementing an interface:

```java
@Tag(Tag.DIV)
@PermitAll
public static class CustomAccessDeniedError extends Component
        implements HasErrorParameter<AccessDeniedException> {
    @Override
    public int setErrorParameter(BeforeEnterEvent event,
            ErrorParameter<AccessDeniedException> parameter) {
        getElement().setText("Access denied.");
        return HttpStatusCode.FORBIDDEN.getCode();
    }
}
```

`HasErrorParameter` error view needs an access control annotation, so that Vaadin allows navigation to it. The example above uses `@PermitAll`, but `@RolesAllowed` can also be used. `@AnonymousAllowed` isn’t recommended, as it exposes information about access restrictions to the anonymous users.

The same applies to custom `RouteNotFoundError` subclasses — they also need a security annotation to be accessible. Note that, for a not-found view, the annotation alone isn’t enough: requests for non-existing pages are denied at the HTTP layer unless the catch-all request rule is also relaxed. See [Router Exception Handling](https://vaadin.com/docs/next/flow/routing/exceptions.md).

If you want to reroute to a different error type, you would do something like the following example. It reroutes unauthorized administrative views to the `RouteNotFoundError` view, which is the default view for `NotFoundException` type.

```java
@Route(value = "admin", layout = MainView.class)
@PageTitle("Admin View")
@RolesAllowed("ADMIN")
@AccessDeniedErrorRouter(rerouteToError = NotFoundException.class)
public class AdminView extends VerticalLayout {
    // ...
}
```

`AccessDeniedErrorRouter` annotation redirects by default to `AccessDeniedException`, if not changed. Annotation is to be used together with `@Route`, or if present, together with access annotation: `@AnonymousAllowed`, `@PermitAll`, `@RolesAllowed`, or `@DenyAll`.

## <a id="navigation-access-control-springs-url-pattern-based-http-security"></a>Navigation Access Control & Spring’s URL-Pattern-Based HTTP Security

The Navigation Access Control feature allows mixing any of the view access annotations with Spring’s URL-pattern-based HTTP security — which possibly exists in older Vaadin Spring Boot applications. However, it may result in extra configuration, since the security annotation on the views and the URL-pattern-based rules must be consistent.

URL-based security can be enabled by activating the `RoutePathAccessChecker` component provided by Flow. To activate it, you need to define a `NavigationAccessControlConfigurer` bean in your Spring configuration, creating a new instance of that class and calling the `withRoutePathAccessChecker()` method.

Activate Both Annotated Views and URL-Pattern-Based Security

```java
@Bean
NavigationAccessControlConfigurer navigationAccessControlConfigurer() {
    return new NavigationAccessControlConfigurer()
            .withAnnotatedViewAccessChecker() // (1)
            .withRoutePathAccessChecker();    // (2)
}
```

1. Activation of annotation base view access checker.

2. Activation of Spring URL-pattern-based checker.

> **Important:** If you add the bean definition method in the same configuration class where you use `VaadinSecurityConfigurer`, the method must be declared `static`, to prevent bootstrap errors because of circular dependencies in bean definitions.

You can also activate only the `RoutePathAccessChecker`, if you prefer to centralize the authorization configuration by only using the Spring Security URL-pattern-based security feature.

Activate Only URL-Pattern-Based Security

```java
@Bean
NavigationAccessControlConfigurer navigationAccessControlConfigurer() {
    return new NavigationAccessControlConfigurer()
            .withRoutePathAccessChecker();
}
```

For more information about navigation access control consult the [related documentation](https://vaadin.com/docs/next/flow/security/advanced-topics/navigation-access-control.md).

Vaadin strongly recommends not to mix Spring’s URL-pattern-based HTTP security and this view-based access control mechanism targeting the same views. Doing so might cause unwanted access configurations, and would be an unnecessary complication in the authorization of views.

## <a id="spring-concurrency-support-with-vaadin"></a>Spring Concurrency Support with Vaadin

Spring Security provides built-in [concurrency support](https://docs.spring.io/spring-security/reference/servlet/integrations/concurrency.html) to propagate security contexts across asynchronous operations. One of the key components for this is `DelegatingSecurityContextExecutor`, which wraps an `Executor` and ensures that the `SecurityContext` is properly propagated to background tasks.

In a Vaadin application, `VaadinSecurityContextHolderStrategy` should be initialized before any custom `DelegatingSecurityContextExecutor` bean is created. This ensures that the correct security context holder is used, preventing potential issues with authentication propagation in async tasks.

To guarantee that `VaadinSecurityContextHolderStrategy` is set before the `DelegatingSecurityContextExecutor` bean is instantiated, consider the following approaches:

- add `@DependsOn("VaadinSecurityContextHolderStrategy")` to the custom `DelegatingSecurityContextExecutor` bean definition to explicitly enforce the initialization order

- instead of relying on implicit ordering, have `VaadinSecurityContextHolderStrategy` directly injected into the bean method definition and manually wire it into the `DelegatingSecurityContextExecutor` instance.

Using @DependsOn

```java
@Bean
@DependsOn("VaadinSecurityContextHolderStrategy")
public DelegatingSecurityContextAsyncTaskExecutor taskExecutor() {
    var delegate = new ThreadPoolTaskExecutor();
    //configure the executor
    delegate.initialize();

    return new DelegatingSecurityContextAsyncTaskExecutor(delegate);
}
```

Injecting VaadinSecurityContextHolderStrategy Manually

```java
@Bean
public DelegatingSecurityContextAsyncTaskExecutor taskExecutor(
    VaadinAwareSecurityContextHolderStrategy strategy) {
    var delegate = new ThreadPoolTaskExecutor();
    //configure the executor
    delegate.initialize();

    var executor = new DelegatingSecurityContextAsyncTaskExecutor(delegate);
    executor.setSecurityContextHolderStrategy(strategy);
    return executor;
}
```

By applying either of these solutions, you ensure that the correct security context holder is used for asynchronous task execution in a Vaadin application.

## <a id="spring-impersonation-with-vaadin"></a>Spring Impersonation with Vaadin

A common use case for secured applications is when a user has a problem and the admin or super user wants to log in as the troubled user to see things from their prospective to better assist them. It can be helpful for customer support analysis when the support person can access the system as the actual user.

An insecure solution — which is basically a security breach — would be to ask the customer to provide their password, or for the administrator to retrieve it from the system. Neither of these methods should be used. Instead, Spring Security has an impersonation feature.

By using impersonation, the system knows who has really logged in. Therefore, it can track an impersonator’s actions for an audit log, if there is one in place.

To add impersonation for a Vaadin application, create the `SwitchUserFilter` bean as follows:

```java
  @Bean
  public SwitchUserFilter switchUserFilter(SecurityContextHolderStrategy strategy) {
    SwitchUserFilter filter = new SwitchUserFilter();
    filter.setSecurityContextHolderStrategy(strategy);
    filter.setUserDetailsService(userDetailsService());
    filter.setSwitchUserMatcher(antMatcher(HttpMethod.GET, "/impersonate"));
    filter.setExitUserMatcher(antMatcher(HttpMethod.GET, "/impersonate/exit"));
    filter.setTargetUrl("/");
    return filter;
  }
```

To secure the impersonation endpoints, configure the HttpSecurity object with the appropriate matchers like so:

```java
  @Bean
  SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    // Authorize impersonation for admin/impersonated admin
    http.authorizeHttpRequests(auth -> auth.requestMatchers("/impersonate").hasAnyRole("ADMIN", "PREVIOUS_ADMINISTRATOR"));
    http.authorizeHttpRequests(auth -> auth.requestMatchers("/impersonate/exit").hasRole("PREVIOUS_ADMINISTRATOR"));

    // Configure Vaadin's security using VaadinSecurityConfigurer
    http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
        configurer.loginView(LoginView.class);
    });

    return http.build();
    // Other configurations
  }
```

This allows users with the `ADMIN` role or when impersonating admin to call the impersonate endpoint.

To impersonate a user, a call to the `impersonate` URL needs to be done.

```java
Button impersonate = new Button("Impersonate user", e ->
  getUI().ifPresent(ui -> ui.getPage().setLocation("/impersonate?username=user"))
);
```

This has the admin impersonate the `user` account without having to know their password.

To exit impersonation, call the exit URL like this:

```java
Button exitImpersonation = new Button("Exit impersonation", e ->
  getUI().ifPresent(ui -> ui.getPage().setLocation("/impersonate/exit"))
);
```

`4C8D835D-4E6E-4D81-BEA1-A865FEB17BAD`
