Skip to main content

Command Palette

Search for a command to run...

Understanding RBAC and Authorization in Spring Security: A Beginner's Guide

Updated
3 min read
Understanding RBAC and Authorization in Spring Security: A Beginner's Guide
I
Welcome to Bits8Byte! I’m Ish, an AI Engineer with 11+ years of experience across software engineering, automation, cloud, and AI-driven systems. This blog is where I share practical insights, technical deep dives, and real-world lessons from building modern software and exploring the fast-moving world of AI. My background spans Java, Spring Boot, Python, FastAPI, AWS, Docker, Kubernetes, DevOps, observability, and automation. Today, my work is increasingly focused on AI engineering, including LLM applications, AI agents, production-grade microservices, and scalable cloud-native architectures. Here, you’ll find thoughtful writing on AI trends, engineering best practices, software architecture, and the mindset required to adapt and grow in the age of AI. My aim is not just to explain technology, but to make it useful, practical, and grounded in real implementation experience. Thanks for stopping by. I hope this space helps you learn something valuable, think more deeply, and stay ahead in a rapidly evolving industry.

1️⃣ Introduction

Authentication is just one part of securing an application. Once a user is authenticated, we need to decide what actions they can perform. This is where authorization comes into play.

In this blog, we’ll explore how Spring Security handles authorization, focusing on Role-Based Access Control (RBAC), method-level security, and hands-on examples to control access to different parts of a Spring Boot application. 🚀


2️⃣ How Does Spring Security Handle Authorization?

🔹 What is Authorization?

Authorization determines what a user can do after authentication. It decides whether the user has permission to perform certain actions.

🔹 Example:

  • A regular user can view their profile but cannot access the admin panel.

  • An admin user can manage user accounts and system settings.

Spring Security provides role-based and permission-based authorization, allowing fine-grained control over access permissions.

📌 Authorization: The process of granting or restricting access to resources based on roles or permissions.


3️⃣ Configuring Role-Based Security (hasRole, hasAuthority)

Role-based security is one of the most common ways to implement authorization. Spring Security provides two methods:

🔹 hasRole() vs. hasAuthority()

  • hasRole("ADMIN") → Checks if the user has the ROLE_ADMIN role.

  • hasAuthority("ROLE_ADMIN") → Checks if the user has the ROLE_ADMIN authority.

🔹 Example:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .requestMatchers("/user/**").hasRole("USER")
            .anyRequest().authenticated()
        )
        .formLogin(Customizer.withDefaults());
    return http.build();
}

📌 Role-Based Access Control (RBAC): A security model where access to resources is granted based on predefined roles assigned to users.

📌 hasRole(): A Spring Security method that checks if a user has a specific role.

📌 hasAuthority(): Similar to hasRole(), but expects the full authority name (e.g., ROLE_ADMIN).


4️⃣ Method-Level Security (@PreAuthorize, @PostAuthorize)

Instead of defining security rules at the request level, we can secure individual methods using annotations like @PreAuthorize and @PostAuthorize.

🔹 @PreAuthorize (Before Execution)

Ensures that the method can be executed only if the user has the required role.

🔹 Example:

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
    userRepository.deleteById(userId);
}

🔹 @PostAuthorize (After Execution)

Used when we need to check authorization after method execution.

🔹 Example:

@PostAuthorize("returnObject.owner == authentication.name")
public User getUser(Long id) {
    return userRepository.findById(id).orElseThrow();
}

📌 @PreAuthorize: An annotation that ensures the method can be executed only if the user meets the security condition.

📌 @PostAuthorize: An annotation that applies authorization checks after the method execution, useful for filtering returned data.


5️⃣ Using Annotations vs. Programmatic Authorization

🔹 Annotations (Declarative Security)

Pros:

  • Simple and easy to read.

  • No need to modify business logic.

  • Works well with Spring AOP (Aspect-Oriented Programming).

Cons:

  • Less flexibility in complex scenarios.

🔹 Programmatic Authorization

For cases where rules need to be dynamically applied, we can use programmatic authorization within the method.

🔹 Example:

public void deletePost(Long postId) {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
        postRepository.deleteById(postId);
    } else {
        throw new AccessDeniedException("You do not have permission to delete this post");
    }
}

📌 Declarative Security: Defining security rules using annotations like @PreAuthorize.

📌 Programmatic Security: Implementing security inside the application logic using manual checks.


6️⃣ ✅ Hands-on: Restricting Access Based on Roles and Authorities

Step 1: Add Spring Security Dependency

Add the following to pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Step 2: Configure Security with Role-Based Access

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .requestMatchers("/user/**").hasRole("USER")
            .anyRequest().authenticated()
        )
        .formLogin(Customizer.withDefaults());
    return http.build();
}

Step 3: Apply Method-Level Security with @PreAuthorize

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
    userRepository.deleteById(userId);
}

Step 4: Define Users with Roles

@Bean
public UserDetailsService userDetailsService() {
    UserDetails user = User.withUsername("user")
            .password(new BCryptPasswordEncoder().encode("password"))
            .roles("USER")
            .build();

    UserDetails admin = User.withUsername("admin")
            .password(new BCryptPasswordEncoder().encode("adminpass"))
            .roles("ADMIN")
            .build();

    return new InMemoryUserDetailsManager(user, admin);
}

Call to Action

Want to learn more about Spring Security? Follow me on Bits8Byte for more hands-on tutorials! 🚀 If you found this helpful, share it with others! 🔥