Spring Security: Authorization

In the domain of application security, once a user's identity is verified through authentication, the next critical step is authorization. Authorization determines what an authenticated user is allowed to do within an application, such as accessing specific resources or performing actions.

Spring Security offers a robust and flexible authorization model that can be tailored to meet complex application security requirements. This blog post explores the concept of authorization in Spring Security through practical use cases and examples, illustrating how to effectively apply authorization controls to secure your application.

The Basics of Authorization in Spring Security

Authorization determines whether an authenticated entity has the right to access specific resources or perform operations. It's about granting or denying permissions based on roles or policies.

Authorization in Spring Security is managed through a combination of domain object security, method security, and URL-based security. It uses the concept of "granted authorities" (roles or privileges) assigned to authenticated users to make authorization decisions. The framework provides various ways to configure authorization, allowing developers to implement fine-grained security policies.

Key Components in Authorization

GrantedAuthority: Represents an authority granted to the principal (user).

SecurityContextHolder: Stores details of the current security context, including the authenticated user's details and granted authorities.

Expression-Based Access Control: Allows for complex security rules using expressions.

Method Security Annotations: @PreAuthorize, @PostAuthorize, @Secured, etc., for securing methods.

Spring Security provides different ways to authorize HTTP requests. Let's look into URL-based or request-level security and method-level security.

URL-Based Security for REST Endpoints

One common requirement is restricting access to certain URLs based on the user's roles. Spring Security simplifies this with its configuration-based approach.

This code snippet showcases how to set up URL-based authorization in Spring Security, defining specific access controls based on HTTP methods and user roles. This allows for a secure and granular approach to protecting resources and ensuring that only authorized users can perform certain actions within your application.
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http.csrf(csrf -> csrf.disable())
                .authorizeHttpRequests((authorize) -> {
                    authorize.requestMatchers(HttpMethod.POST, "/api/**").hasRole("ADMIN");
                    authorize.requestMatchers(HttpMethod.PUT, "/api/**").hasRole("ADMIN");
                    authorize.requestMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN");
                    authorize.requestMatchers(HttpMethod.GET, "/api/**").hasAnyRole("ADMIN", "USER");
                    authorize.requestMatchers(HttpMethod.PATCH, "/api/**").hasAnyRole("ADMIN", "USER");
                    authorize.anyRequest().authenticated();
                }).httpBasic(Customizer.withDefaults());

        http.exceptionHandling( exception -> exception
                .authenticationEntryPoint(authenticationEntryPoint));

        http.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
The SecurityFilterChain is responsible for specifying how security should be applied to HTTP requests in a Spring application.

The authorizeHttpRequests() method specifies authorization rules for HTTP requests based on URLs and HTTP methods.

authorize.requestMatchers(HttpMethod.POST, "/api/**").hasRole("ADMIN"): Specifies that only users with the "ADMIN" role are allowed to make POST requests to any URL that matches the /api/** pattern.

Similar rules are set for PUT, DELETE, GET, and PATCH requests. For PUT, DELETE, and PATCH methods, only "ADMIN" users are allowed. For GET requests, both "ADMIN" and "USER" roles are permitted, providing broader access.

authorize.anyRequest().authenticated(): This rule ensures that any request not matching the previous patterns must be authenticated, regardless of the user's role. It is a catch-all rule that secures all other endpoints.

Method-Level Security

You can enable method-level security in your Spring application by annotating any @Configuration class with @EnableMethodSecurity. Then, you can immediately annotate any Spring-managed class or method with @PreAuthorize, @PostAuthorize, @PreFilter, and @PostFilter to authorize method invocations, including the input parameters and return values.

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 this endpoint can only be accessed by users with the 'ADMIN' role.

@GetMapping("/admin"): This maps HTTP GET requests to /api/admin to the helloAdmin() method. When accessed, it returns a response with "Hello Admin".

@PreAuthorize("hasRole('USER')"): This annotation on the helloUser() method restricts access to users with the 'USER' role. Spring Security enforces this role check before allowing access to the method.

@GetMapping("/user"): Maps HTTP GET requests to /api/user to the helloUser() method. Authorized users with the 'USER' role will receive a "Hello User" response.

Conclusion

By understanding and leveraging the various authorization mechanisms available in Spring Security, developers can ensure that their applications are secure and maintain a fine balance between accessibility and control. Whether securing web URLs or applying fine-grained access control on service methods, Spring Security protects sensitive resources and functionalities in your applications.

Comments