> Markdown version of [Securing Plain Java Applications](https://vaadin.com/docs/latest/flow/security/advanced-topics/securing-plain-java-app). Section index: [llms.txt](https://vaadin.com/docs/latest/flow/llms.txt)

# Securing Plain Java Applications

As described on the [enabling security](https://vaadin.com/docs/latest/flow/security/enabling-security.md) documentation page, Vaadin Flow comes with built-in security helpers that are most convenient to implement with Spring Boot and Spring Security. Although it’s recommended to use Spring Security, it isn’t always necessary.

This page describes how to use Vaadin Flow’s built-in security helpers in a *plain* Java project.

> **Note:** Separate instructions are available for Spring Boot and Spring Security. If your project is a Spring Boot project, follow the instructions provided on the [enabling security](https://vaadin.com/docs/latest/flow/security/enabling-security.md) documentation page.

Vaadin built-in helpers enable a view-based access control mechanism that uses the `@AnonymousAllowed`, `@PermitAll`, `@RolesAllowed`, and `@DenyAll` annotations on view classes to define the access control rules.

By default, any view without an annotation is secured; it acts as if it has the `@DenyAll` annotation. To enable and use this mechanism, the following should be added to a plain Java Flow application, if they aren’t already included:

- Security realm;

- Log-in view and log-out capability;

- `VaadinServiceInitListener` that adds `NavigationAccessControl` as the `BeforeEnterListener` of all UIs; and a

- Service Provider under `META-INF/services` to load above the custom `ServiceInitListener` via the Java Service Provider Interface (SPI) loading mechanism.

## <a id="configuring-a-security-realm"></a>Configuring a Security Realm

A *security realm* is a mechanism for storing and mapping users to their passwords and roles. Configuring a security realm depends on the application server you’re using to run the Vaadin application. For example, if you use Apache Tomcat or TomEE, follow [Tomcat Realm Configuration](https://tomcat.apache.org/tomcat-10.0-doc/realm-howto.html) instructions.

## <a id="handling-user-log-in-out"></a>Handling User Log In & Out

You can handle log-in and log-out in many ways. The same applies to getting the authenticated user for a request. The view-based access control implementation in Vaadin uses `getUserPrincipal()` and `isUserInRole(String)` in `HttpServletRequest` to check whether the currently authenticated user has access to the view. However, you need a way to provide the user information in the request.

The following example uses the currently active Vaadin servlet request. It shows how to check whether the user is currently authenticated to the application. The request isn’t available in background threads, so the `isAuthenticated()` method shows authentication state only in Vaadin request processing threads. Otherwise, it always returns `false`.

The example below also shows how to authenticate the user with the given credentials. The `authenticate()` method fails if it’s called from a background thread. Session ID is changed once the user logs in. This protects the application from Session Fixation vulnerabilities. As an alternative, the old session can be invalidated and re-created.

Finally, the example demonstrates how to log out the user by invalidating the HTTP session and redirecting to the home page:

`SecurityUtils.java`

```java
public class SecurityUtils {

    private static final String LOGOUT_SUCCESS_URL = "/";

    public static boolean isAuthenticated() {
        VaadinServletRequest request = VaadinServletRequest.getCurrent();
        return request != null && request.getUserPrincipal() != null;
    }

    public static boolean authenticate(String username, String password) {
        VaadinServletRequest request = VaadinServletRequest.getCurrent();
        if (request == null) {
            // This is in a background thread and we can't access the request to
            // log in the user
            return false;
        }
        try {
            request.login(username, password);
            // change session ID to protect against session fixation
            request.getHttpServletRequest().changeSessionId();
            return true;
        } catch (ServletException e) {
            // login exception handle code omitted
            return false;
        }
    }

    public static void logout() {
        UI.getCurrentOrThrow().getPage().setLocation(LOGOUT_SUCCESS_URL);
        VaadinSession.getCurrent().getSession().invalidate();
    }
}
```

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

Having a log-in view is one of the basic requirements of many authentication and authorization mechanisms. It serves to redirect anonymous users to that page before granting access to view any protected resources.

`LoginView.java`

```java
@Route("login")
@PageTitle("Login")
@AnonymousAllowed
public class LoginView extends VerticalLayout implements BeforeEnterObserver,
        ComponentEventListener<AbstractLogin.LoginEvent> {

    private static final String LOGIN_SUCCESS_URL = "/";

    private LoginForm login = new LoginForm();

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

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

        login.addLoginListener(this);

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

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

    @Override
    public void onComponentEvent(AbstractLogin.LoginEvent loginEvent) {
        boolean authenticated = SecurityUtils.authenticate(
                loginEvent.getUsername(), loginEvent.getPassword());
        if (authenticated) {
            UI.getCurrentOrThrow().getPage().setLocation(LOGIN_SUCCESS_URL);
        } else {
            login.setError(true);
        }
    }
}
```

In this example, Vaadin’s Login Form component is used for the sake of brevity. However, you could instead implement a more verbose log-in view.

## <a id="log-out-capability"></a>Log-Out Capability

Typically, you’d let the user log out by using a log-out button. The following example shows a basic implementation of a log-out button shown on the header of the main layout:

`MainLayout.java`

```java
public class MainLayout extends AppLayout {

    public MainLayout() {
        H1 logo = new H1("Vaadin CRM");
        logo.addClassName("logo");
        HorizontalLayout header;
        if (SecurityUtils.isAuthenticated()) {
            Button logout = new Button("Logout", click ->
                    SecurityUtils.logout());
            header = new HorizontalLayout(logo, logout);
        } else {
            header = new HorizontalLayout(logo);
        }

        // Other page components omitted.

        addToNavbar(header);
    }
}
```

## <a id="adding-vaadinserviceinitlistener"></a>Adding `VaadinServiceInitListener`

To restrict access to views, a `VaadinServiceInitListener` must be registered for the `VaadinService` to initialize and enable the `NavigationAccessControl` for all UIs:

`NavigationControlAccessCheckerInitializer.java`

```java
import com.vaadin.flow.server.ServiceInitEvent;
import com.vaadin.flow.server.VaadinServiceInitListener;
import com.vaadin.flow.server.auth.NavigationAccessControl;
import org.vaadin.example.views.login.LoginView;

public class NavigationAccessCheckerInitializer implements VaadinServiceInitListener {

    private NavigationAccessControl accessControl;

    public NavigationControlAccessCheckerInitializer() {
        accessControl = new NavigationAccessControl(); // (1)
        accessControl.setLoginView(LoginView.class); // (2)
    }

    @Override
    public void serviceInit(ServiceInitEvent serviceInitEvent) {
        serviceInitEvent.getSource().addUIInitListener(uiInitEvent -> {
            uiInitEvent.getUI().addBeforeEnterListener(accessControl); // (3)
        });
    }
}
```

This code contains some notable components of the view-based access control mechanism:

1. `NavigationAccessControl`, which is at the core of this access control mechanism, is instantiated. It’s enabled by default.

2. The `LoginView` class is set to the `accessControl` instance. Now it knows where to redirect unauthenticated users.

3. The `accessControl` instance is set as the `BeforeEnterListener` in the overridden `serviceInit()` method. Now it’s ready to intercept attempts to enter all views.

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

This class still needs to be loaded, so you should follow the instructions in the next section.

## <a id="enable-loading-of-vaadinserviceinitlistener"></a>Enable Loading of VaadinServiceInitListener

To enable the Java SPI loading mechanism to load the `NavigationControlAccessCheckerInitializer` as the `VaadinServiceInitListener`, there are a few things to do.

First, under the `resources/META-INF/services` directory, create a file named exactly `com.vaadin.flow.server.VaadinServiceInitListener`.

Next, put the fully qualified name of the `NavigationControlAccessCheckerInitializer` into this newly created file. For example, if the `NavigationControlAccessCheckerInitializer` class is in the `org.vaadin.example.security` package, the following value should be in the file, `org.vaadin.example.security.NavigationControlAccessCheckerInitializer`.

This Service Provider configuration file triggers the Java SPI loading mechanism to load `NavigationControlAccessCheckerInitializer` during application startup. For more information on this, see [VaadinServiceInitListener](https://vaadin.com/docs/latest/flow/advanced/service-init-listener.md).

## <a id="access-annotations"></a>Access Annotations

Before some access annotation examples, consider the annotations and their meaning when applied to a view:

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

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

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

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

## <a id="examples"></a>Examples

Below are some usage examples:

Allow All Users to Navigate to View

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

Allow Only Authenticated Users to Navigate to View

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

Allow Only Users with `ADMIN` Role to Navigate to View

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

Now, if the application is started by navigating to `http://localhost:8080`, `PublicView` contents should be available without any authentication. However, by navigating to `http://localhost:8080/private` or `http://localhost:8080/admin`, the user is redirected to the specified `LoginView`.

If the user is already authenticated and tries to navigate to a view for which they have no permission, an error message is displayed. The message depends on the application mode: In development mode, Vaadin shows an *Access denied* message with the list of available routes. In production mode, Vaadin shows the `RouteAccessDeniedError` view, which shows the *Could not navigate to 'RequestedRouteName'* message by default. For security reasons, the message doesn’t say whether the navigation target exists.

The following example shows how the security annotations are inherited from the closest parent class that has them:

Inheriting Security Annotations from Parent Class

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

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

Annotating a child class overrides any inherited annotations. Interfaces aren’t checked for annotations, only classes. By design, the annotations aren’t read from parent layouts or parent views. This would make it unnecessarily complex to determine which security level should be applied. If multiple annotations are specified on a single view class, the following rules are applied:

- `DenyAll` overrides other annotations;

- `AnonymousAllowed` overrides `RolesAllowed` and `PermitAll`; and

- `RolesAllowed` overrides `PermitAll`.

You shouldn’t specify more than one of the above access annotations on a view class. It’s confusing and probably has no logical purpose.

`5D3E1BB8-9D7C-4FAD-9381-8DBB3C65F6A8`
