CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-vaadin--vaadin-core

Vaadin Platform (vaadin-core) - Core component of the Vaadin web framework platform

Overview
Eval results
Files

security.mddocs/

Security

Vaadin provides comprehensive security features for controlling access to views and securing applications, with seamless integration with Spring Security and Jakarta EE security.

Security Annotations

Annotations for controlling access to views and endpoints.

/**
 * Allows anonymous (unauthenticated) access to a view
 * Place on view classes to make them publicly accessible
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface AnonymousAllowed {
}

/**
 * Allows all authenticated users to access a view
 * Place on view classes to require authentication but no specific roles
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface PermitAll {
}

/**
 * Restricts access to users with specific roles
 * Place on view classes to require specific role membership
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface RolesAllowed {
    /**
     * Array of role names that are allowed to access the view
     * @return Array of allowed role names
     */
    String[] value();
}

/**
 * Denies all access to a view
 * Place on view classes to completely block access
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface DenyAll {
}

Usage Examples:

import com.vaadin.flow.server.auth.AnonymousAllowed;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;
import jakarta.annotation.security.DenyAll;

// Public view accessible to everyone
@Route("welcome")
@AnonymousAllowed
public class WelcomeView extends VerticalLayout {
    public WelcomeView() {
        add(new H1("Welcome!"));
        add(new Paragraph("This page is public"));
    }
}

// View accessible to any authenticated user
@Route("dashboard")
@PermitAll
public class DashboardView extends VerticalLayout {
    public DashboardView() {
        add(new H1("Dashboard"));
        add(new Paragraph("You are logged in"));
    }
}

// View restricted to specific roles
@Route("admin")
@RolesAllowed({"ADMIN", "SUPER_USER"})
public class AdminView extends VerticalLayout {
    public AdminView() {
        add(new H1("Admin Panel"));
        add(new Paragraph("Admin access only"));
    }
}

// View completely blocked
@Route("maintenance")
@DenyAll
public class MaintenanceView extends VerticalLayout {
    // This view cannot be accessed
}

Spring Security Integration

Classes for integrating Vaadin with Spring Security.

/**
 * Base configuration class for Spring Security with Vaadin
 * Extend this class to configure security for Vaadin applications
 */
abstract class VaadinWebSecurity extends WebSecurityConfigurerAdapter {
    /**
     * Configures HTTP security for the application
     * @param http - HttpSecurity to configure
     * @throws Exception if configuration fails
     */
    protected void configure(HttpSecurity http) throws Exception;

    /**
     * Configures web security for the application
     * @param web - WebSecurity to configure
     * @throws Exception if configuration fails
     */
    protected void configure(WebSecurity web) throws Exception;

    /**
     * Sets the login view and configures logout
     * @param http - HttpSecurity to configure
     * @param loginPath - Path to login view (e.g., "/login")
     * @param logoutSuccessUrl - URL to redirect after logout
     * @throws Exception if configuration fails
     */
    protected void setLoginView(HttpSecurity http, String loginPath,
                                 String logoutSuccessUrl) throws Exception;

    /**
     * Sets the login view
     * @param http - HttpSecurity to configure
     * @param loginPath - Path to login view
     * @throws Exception if configuration fails
     */
    protected void setLoginView(HttpSecurity http, String loginPath) throws Exception;
}

/**
 * Context for accessing authentication information
 * Injectable Spring bean for working with authentication
 */
class AuthenticationContext {
    /**
     * Checks if the current user is authenticated
     * @return true if user is authenticated
     */
    boolean isAuthenticated();

    /**
     * Gets the authenticated user object
     * @param userType - Class of the user object
     * @return Optional containing user if authenticated
     */
    <T> Optional<T> getAuthenticatedUser(Class<T> userType);

    /**
     * Gets principal name of authenticated user
     * @return Optional containing principal name
     */
    Optional<String> getPrincipalName();

    /**
     * Logs out the current user
     */
    void logout();
}

Usage Examples:

import com.vaadin.flow.spring.security.VaadinWebSecurity;
import com.vaadin.flow.spring.security.AuthenticationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

// Security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends VaadinWebSecurity {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        setLoginView(http, "/login", "/");
    }
}

// Using AuthenticationContext in a view
@Route("profile")
@PermitAll
public class ProfileView extends VerticalLayout {
    public ProfileView(AuthenticationContext authContext) {
        if (authContext.isAuthenticated()) {
            Optional<UserDetails> userDetails =
                authContext.getAuthenticatedUser(UserDetails.class);

            userDetails.ifPresent(user -> {
                add(new H2("Profile"));
                add(new Paragraph("Username: " + user.getUsername()));
            });

            Button logoutButton = new Button("Logout", e -> {
                authContext.logout();
            });
            add(logoutButton);
        }
    }
}

Login Components

class LoginForm extends Component {
    LoginForm();
    void setAction(String action);
    void setError(boolean error);
    void setErrorMessage(String errorMessage);
    void setForgotPasswordButtonVisible(boolean visible);
    void setI18n(LoginI18n i18n);
    Registration addLoginListener(ComponentEventListener<LoginEvent> listener);
}

class LoginOverlay extends Component {
    LoginOverlay();
    void open();
    void setOpened(boolean opened);
    void setTitle(String title);
    void setDescription(String description);
    void setAction(String action);
    void setError(boolean error);
    Registration addLoginListener(ComponentEventListener<LoginOverlayEvent> listener);
}

class LoginEvent extends ComponentEvent<LoginForm> {
    String getUsername();
    String getPassword();
}

Examples:

@Route("login")
@AnonymousAllowed
public class LoginView extends VerticalLayout {
    public LoginView() {
        LoginForm loginForm = new LoginForm();
        loginForm.setAction("login");
        loginForm.setForgotPasswordButtonVisible(false);

        loginForm.addLoginListener(e ->
            System.out.println("Login: " + e.getUsername())
        );

        add(new H1("Login"), loginForm);
        setAlignItems(Alignment.CENTER);
    }
}

@Route("")
@AnonymousAllowed
public class WelcomeView extends VerticalLayout {
    private LoginOverlay loginOverlay;

    public WelcomeView() {
        loginOverlay = new LoginOverlay();
        loginOverlay.setTitle("My Application");
        loginOverlay.setDescription("Enterprise System");
        loginOverlay.setAction("login");

        LoginI18n i18n = LoginI18n.createDefault();
        i18n.getForm().setTitle("Sign In");
        i18n.getForm().setUsername("Email");
        loginOverlay.setI18n(i18n);

        loginOverlay.setOpened(true);
        add(loginOverlay);
    }
}

Menu Access Control

Interfaces for controlling menu visibility based on user permissions.

/**
 * Interface for controlling access to menu items
 */
interface MenuAccessControl {
    /**
     * Populates menu based on user access rights
     * @param request - Current HTTP request
     * @return MenuRegistry with accessible items
     */
    MenuRegistry populateClientSideMenu(HttpServletRequest request);

    /**
     * Checks if user can access a menu entry
     * @param entry - Menu entry to check
     * @param request - Current HTTP request
     * @return true if access is allowed
     */
    boolean canAccessMenuEntry(MenuEntry entry, HttpServletRequest request);
}

/**
 * Default implementation of menu access control
 * Uses security annotations to determine access
 */
class DefaultMenuAccessControl implements MenuAccessControl {
    /**
     * Creates default menu access control
     * @param accessChecker - Access checker for views
     */
    DefaultMenuAccessControl(AccessAnnotationChecker accessChecker);
}

/**
 * Checker for security annotations on views
 */
class AccessAnnotationChecker {
    /**
     * Checks if principal has access to a view
     * @param viewClass - View class to check
     * @param principal - User principal
     * @param roleChecker - Function to check roles
     * @return true if access is allowed
     */
    boolean hasAccess(Class<?> viewClass, Principal principal,
                      Function<String, Boolean> roleChecker);
}

Security Best Practices

When securing Vaadin applications:

  1. Always use annotations on view classes: Place security annotations (@AnonymousAllowed, @PermitAll, @RolesAllowed, @DenyAll) on all route classes.

  2. Deny by default: Views without security annotations are denied by default. Always be explicit about access.

  3. Server-side validation: Always validate user permissions on the server side, never rely solely on UI-level hiding.

  4. Use Spring Security integration: Leverage VaadinWebSecurity for comprehensive Spring Security integration.

  5. Secure endpoints: If using Vaadin Fusion or Hilla, secure backend endpoints with security annotations.

  6. Session management: Configure proper session timeout and management in application properties.

Example Comprehensive Security Setup:

// Security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends VaadinWebSecurity {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // Vaadin-specific security configuration
        super.configure(http);

        // Set login view
        setLoginView(http, LoginView.class);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }
}

// Login view (public)
@Route("login")
@AnonymousAllowed
public class LoginView extends VerticalLayout {
    public LoginView(AuthenticationContext authContext) {
        if (authContext.isAuthenticated()) {
            // Redirect if already logged in
            getUI().ifPresent(ui -> ui.navigate(""));
        }

        LoginForm loginForm = new LoginForm();
        loginForm.setAction("login");
        loginForm.setForgotPasswordButtonVisible(false);

        add(new H1("My Application"), loginForm);
    }
}

// Main view (authenticated users only)
@Route("")
@PermitAll
public class MainView extends AppLayout {
    public MainView(AuthenticationContext authContext) {
        H1 title = new H1("My Application");

        authContext.getAuthenticatedUser(UserDetails.class)
            .ifPresent(user -> {
                Button logout = new Button("Logout", e -> authContext.logout());
                addToNavbar(title, logout);
            });

        addToDrawer(createMenu(authContext));
    }

    private Component createMenu(AuthenticationContext authContext) {
        SideNav menu = new SideNav();
        menu.addItem(new SideNavItem("Dashboard", "/dashboard"));

        // Conditionally show admin link
        authContext.getAuthenticatedUser(UserDetails.class)
            .ifPresent(user -> {
                if (user.getAuthorities().stream()
                    .anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
                    menu.addItem(new SideNavItem("Admin", "/admin"));
                }
            });

        return menu;
    }
}

// Admin view (admin role only)
@Route(value = "admin", layout = MainView.class)
@RolesAllowed("ADMIN")
public class AdminView extends VerticalLayout {
    public AdminView() {
        add(new H2("Admin Panel"));
        add(new Paragraph("Only administrators can see this."));
    }
}

Jakarta EE Security

Vaadin also supports Jakarta EE (formerly Java EE) security annotations:

import jakarta.annotation.security.RolesAllowed;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.DenyAll;

@Route("enterprise")
@RolesAllowed("ENTERPRISE_USER")
public class EnterpriseView extends VerticalLayout {
    // Jakarta EE security integration
}

CSRF Protection

Vaadin automatically handles CSRF (Cross-Site Request Forgery) protection:

  • CSRF tokens are automatically included in all server requests
  • No manual configuration needed for standard Vaadin applications
  • Works seamlessly with Spring Security CSRF protection

Related Documentation

  • Spring Security: https://spring.io/projects/spring-security
  • Jakarta Security: https://jakarta.ee/specifications/security/
  • Vaadin Security Guide: https://vaadin.com/docs/latest/security

Install with Tessl CLI

npx tessl i tessl/maven-com-vaadin--vaadin-core

docs

advanced.md

components.md

core-framework.md

data-integration.md

index.md

layouts.md

security.md

themes-styling.md

tile.json