@PreAuthorize Annotation in Spring Security

The @PreAuthorize annotation in Spring Security provides a declarative way to add method-level security checks to your Spring Boot applications. This tutorial guides you through setting up and using @PreAuthorize effectively, ensuring users only call REST APIs with specific roles or permissions.

@PreAuthorize is a Spring Security annotation used to specify an expression that should be evaluated before a method is invoked to determine whether the caller is authorized to execute it.

Step 1: Add Spring Security to Your Project

Ensure Spring Security is included in your project. For Maven, add these dependencies to your pom.xml:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

For Gradle, include in your build.gradle:
implementation 'org.springframework.boot:spring-boot-starter-security'

Step 2: Enable Method Security 

To apply Spring Security to specific methods in the Rest Controller class of your Spring Boot application, you must enable method-level security. To do that, you must use the @EnableMethodSecurity annotation.
@Configuration
@EnableMethodSecurity
public class SpringSecurityConfig {

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http.csrf(csrf -> csrf.disable())
                .authorizeHttpRequests((authorize) -> {
                    authorize.requestMatchers(HttpMethod.GET, "/api/user").hasRole("USER");
                    authorize.requestMatchers(HttpMethod.GET, "/api/admin").hasRole("ADMIN");
                    authorize.anyRequest().authenticated();
                }).httpBasic(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService(){

        UserDetails ramesh = User.builder()
                .username("ramesh")
                .password(passwordEncoder().encode("password"))
                .roles("USER")
                .build();

        UserDetails admin = User.builder()
                .username("admin")
                .password(passwordEncoder().encode("admin"))
                .roles("ADMIN")
                .build();

        return new InMemoryUserDetailsManager(ramesh, admin);
    }
}
@EnableMethodSecurity is a Spring annotation that enables method-level security in a Spring application. When you use this annotation, Spring will create a proxy for the class containing the secured methods and intercept calls to those methods to check if the caller has the required permissions to execute them. 

This annotation works together with other annotations, such as @PreAuthorize, @PostAuthorize, @Secured, and @RolesAllowed, which specify the access control rules for the methods. 

For example, you can use @PreAuthorize to specify that only users with a certain role or authority can call a particular method. Alternatively, you can use @PostAuthorize to specify that the method should only return data the caller is authorized to see.

Step 3: Secure REST APIs using @PreAuthorize Annotation

The code below demonstrates the role-based authorization for RESTful endpoints using Spring Security.
@RestController
@RequestMapping("/api/")
public class AdminController {

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/admin")
    public ResponseEntity<String> helloAdmin(){
        return ResponseEntity.ok("Hello Admin");
    }

    @PreAuthorize("hasRole('USER')")
    @GetMapping("/user")
    public ResponseEntity<String> helloUser(){
        return ResponseEntity.ok("Hello User");
    }
}
@PreAuthorize("hasRole('ADMIN')"): This is applied to the helloAdmin() method. It specifies that users with the 'ADMIN' role can only access this endpoint. 

@PreAuthorize("hasRole('USER')"): This annotation on the helloUser() method restricts access to users with the 'USER' role. 

Conclusion

This tutorial taught you how to use Spring method-level security to secure RestController methods with @PreAuthorize annotation.

Comments