In modern web applications, securing resources based on user roles is a crucial requirement. Role-Based Access Control in Spring Boot enables fine-grained access management by assigning specific permissions to roles rather than individual users. This approach simplifies permission handling and enhances security.
In this post, we will explore how to implement RBAC in Spring Boot using Spring Security, with a practical example that includes custom roles, protected endpoints, and method-level security.

๐ง Project Setup
Use Spring Initializr or your favorite tool to generate a Spring Boot project with the following dependencies:
- Spring Web
- Spring Security
- Spring Data JPA
- H2 Database (for demo purposes)
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-starter-data-jpa
com.h2database
h2
runtime
๐ค User and Role Entities
Create the following JPA entities to represent users and their roles.
@Entity
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name; // e.g., ROLE_USER, ROLE_ADMIN
}
@Entity
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@ManyToMany(fetch = FetchType.EAGER)
private Set roles = new HashSet<>();
}
๐ Spring Security Configuration
Configure Spring Security to load user roles and enforce access control.
UserDetailsService Implementation
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
AppUser user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
Set authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
}
SecurityConfig Class
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Autowired
private CustomUserDetailsService userDetailsService;
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.httpBasic();
return http.build();
}
@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder())
.and()
.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
๐ Controller with Role-Based Access
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/profile")
public String userProfile() {
return "Welcome User!";
}
}
@RestController
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/dashboard")
public String adminDashboard() {
return "Welcome Admin!";
}
}
๐งช Sample Data Initialization
@Component
public class DataLoader implements CommandLineRunner {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Autowired
private PasswordEncoder encoder;
@Override
public void run(String... args) {
Role admin = roleRepository.save(new Role(null, "ROLE_ADMIN"));
Role user = roleRepository.save(new Role(null, "ROLE_USER"));
AppUser adminUser = new AppUser();
adminUser.setUsername("admin");
adminUser.setPassword(encoder.encode("admin123"));
adminUser.setRoles(Set.of(admin));
AppUser normalUser = new AppUser();
normalUser.setUsername("user");
normalUser.setPassword(encoder.encode("user123"));
normalUser.setRoles(Set.of(user));
userRepository.saveAll(List.of(adminUser, normalUser));
}
}
โ Testing the RBAC
Use Postman or curl to test:
# Admin access
curl -u admin:admin123 http://localhost:8080/admin/dashboard
# User access
curl -u user:user123 http://localhost:8080/user/profile
Try accessing /admin/dashboard with a user account to verify that RBAC works.
๐ Conclusion
Implementing Role-Based Access Control in Spring Boot allows you to manage access cleanly and securely. By leveraging Spring Security and defining user roles, you can protect sensitive endpoints and delegate access only to the right users.
RBAC in Spring Boot is a scalable solution especially when combined with database-driven roles and method-level security.