> Markdown version of [Protect Services](https://vaadin.com/docs/next/building-apps/security/protect-services). Section index: [llms.txt](https://vaadin.com/docs/next/building-apps/llms.txt)

# Protect Services

A secure application relies on multiple layers of protection, including both views and application services. Even when your views are protected, you should also protect the application services. This is important if you have views that allow users with different roles to do different things. If you, for instance, forget to disable a button for users lacking a particular role, and don’t protect your services, you have created a privilege escalation. See [Controlling Access within Views](https://vaadin.com/docs/next/building-apps/security/protect-views.md#controlling-access-within-views) for how to restrict what users can do inside a view.

## <a id="introducing-method-security"></a>Introducing Method Security

In a Flow application, services are standard Spring beans that are injected into views and used directly. Since services are accessed directly from views, they must be secured at the method level using **Spring method security**. Browser-callable services that React views call are protected differently. See [Secure React Views](https://vaadin.com/docs/next/building-apps/react/security.md#protecting-browser-callable-services) for details.

Spring Security protects services by creating a proxy that intercepts method calls. This ensures access control is enforced before execution, as shown in the following diagram:

[Image: A diagram of a flow view]

In this guide, you’ll only learn the minimum to get started with Spring method security in a Vaadin application. For more in-depth information, see the [Spring Security Reference Manual](https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html).

## <a id="enabling-method-security"></a>Enabling Method Security

To enable method security, add `@EnableMethodSecurity` to your security configuration class:

`SecurityConfig.java`

```java
@EnableWebSecurity
// tag::snippet[]
@EnableMethodSecurity
// end::snippet[]
@Configuration
class SecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
            configurer.loginView(LoginView.class);
        });
        return http.build();
    }
    ...
}
```

> **Caution: Test the method security**
>
> Without `@EnableMethodSecurity`, **all services remain unprotected** — even if you annotate methods with security rules! Always verify that method security is enabled with automatic tests, as shown in [Testing Method Security](#testing-method-security).

## <a id="securing-the-services"></a>Securing the Services

Spring Security uses different annotations to secure your services. The most flexible ones, which are enabled by default, are `@PreAuthorize`, `@PostAuthorize`, `@PreFilter`, and `@PostFilter`. In this guide, you’ll only learn how to use `@PreAuthorize`.

You can annotate both **service classes** and individual **service methods**. An annotation placed on the class applies to **all public methods** of the class. An annotation placed on a method **overrides any annotation on the class**.

`@PreAuthorize` takes as its single argument a Spring Expression Language (SpEL) expression that must evaluate to `true` to grant access. Although you can do some quite advanced things with SpEL, the most common methods you’ll want to use are:

- `permitAll` allows **anyone** to call the method.

- `isAuthenticated` allows any **authenticated** user to call the method.

- `hasRole` / `hasAnyRole` allows users **having the roles** specified to call the method.

- `denyAll` prevents **anyone** from calling the method.

You use the SpEL methods like this:

```java
@Service
// tag::snippet[]
@PreAuthorize("isAuthenticated()") // (1)
// end::snippet[]
public class ProtectedService {

    public void callableByAllUsers() { // (2)
    }

// tag::snippet[]
    @PreAuthorize("hasRole('" + Roles.ADMIN + "')") // (3)
// end::snippet[]
    public void callableByAdminsOnly(MyData data) {
    }
}
```

1. Allows all authenticated users to call the service by default.

2. Inherits its access permissions from the class-level annotation.

3. Overrides the class-level annotation to allow access to administrators only. Note the single quotes `'` around the role name.

## <a id="testing-method-security"></a>Testing Method Security

Because services are ordinary Spring beans, you can test their security rules with plain Spring Boot tests, without involving any views. Add the Spring Security test dependency to your project, if it isn’t there already:

```xml
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>
```

Then call the service as different users, and check that the calls that should be denied throw an `AccessDeniedException`:

```java
@SpringBootTest
class ProtectedServiceTest {

    @Autowired
    ProtectedService service;

    @Test
    @WithAnonymousUser // (1)
    void anonymous_users_cannot_call_the_service() {
        assertThrows(AccessDeniedException.class,
            () -> service.callableByAllUsers());
    }

    @Test
    @WithMockUser(roles = Roles.USER) // (2)
    void users_cannot_call_admin_methods() {
        assertThrows(AccessDeniedException.class,
            () -> service.callableByAdminsOnly(new MyData()));
    }

    @Test
    @WithMockUser(roles = Roles.ADMIN)
    void admins_can_call_admin_methods() {
        assertDoesNotThrow(() -> service.callableByAdminsOnly(new MyData()));
    }
}
```

1. Runs the test as an anonymous user. Without an annotation like this, there’s no authentication at all, and Spring Security throws a different exception.

2. Runs the test as an authenticated user with the `USER` role.

If `@EnableMethodSecurity` is missing, the first two tests fail, because nothing stops the calls. The tests therefore protect you against both a missing configuration and a mistake in the security rules.

To test that your views are protected, see [Test View Access Control](https://vaadin.com/docs/next/building-apps/testing/browserless/test-view-access.md).
