Spring Security Role-Based Access Control (RBAC) Explained with Real-Time Examples
Introduction :
In modern applications, not every user should have access to every feature. For example, in a banking application, customers can view their accounts, employees can process requests, and administrators can manage users. Allowing all users to access all resources would be a serious security risk.
This is where Role-Based Access Control (RBAC) comes into the picture.
In this article, we'll understand RBAC in Spring Security, learn how roles work with JWT Authentication, and implement role-based authorization using real-time examples.
What is RBAC?
RBAC (Role-Based Access Control) is a security mechanism that restricts access to resources based on user roles.
Instead of assigning permissions individually to every user, users are assigned roles, and permissions are associated with those roles.
Common Roles in Applications
ADMIN
MANAGER
EMPLOYEE
USER
CUSTOMER
When a user logs in, the system checks their role and grants access only to the resources allowed for that role.
Authentication and Authorization
Many developers confuse these two concepts.
Authentication
Authentication verifies who the user is.
Example:
Username: Sulochana
Password: password123
If the credentials are correct, the user is authenticated.
Authorization
Authorization determines what the authenticated user can access.
Example:
ADMIN can manage users.
USER can view profile information.
MANAGER can approve requests.
JWT Authentication handles identity verification, while RBAC handles access control.
Real-Time Example
Let's consider an Online Banking Application.
CUSTOMER
Can:
View account details
Transfer money
View transaction history
Cannot:
Create new users
Access admin dashboard
EMPLOYEE
Can:
Verify customer requests
Process transactions
Cannot:
Manage system users
ADMIN
Can:
Create users
Delete users
Access admin dashboard
Manage application settings
RBAC ensures each user can access only the resources required for their job.
Step 1: Create Role Enum
First, define the available roles in the application.
public enum Role {
USER,
MANAGER,
ADMIN
}
Using an Enum helps prevent typing mistakes and keeps role management consistent.
Why do we use Enum for Roles?
Instead of storing roles as plain strings:
private String role;
we use:
public enum Role {
USER,
MANAGER,
ADMIN
}and then:
@Enumerated(EnumType.STRING)
private Role role;1. Prevents Typing Mistakes
With String:
user.setRole("ADMIN");
user.setRole("admin");
user.setRole("Admin");
user.setRole("ADMN"); // typoAll of these compile successfully, which can cause authorization issues.
2. Improves Code Readability
String approach:
if(user.getRole().equals("ADMIN")) {
// logic
}Enum approach:
if(user.getRole() == Role.ADMIN) {
// logic
}Cleaner and easier to understand.
3. Better Maintainability
Suppose your application grows and you add:
public enum Role {
USER,
MANAGER,
ADMIN,
SUPER_ADMIN
}Now the role is available everywhere in the project automatically.
Step 2: Add Role to User Entity
Store the user's role in the database.
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
@Enumerated(EnumType.STRING)
private Role role;
}
Why Use EnumType.STRING?
Good:
ADMIN
USER
MANAGER
Avoid:
0
1
2
Using strings makes database records easier to understand and maintain.
Step 3: Include Roles in UserDetails
Spring Security needs to know the user's authorities.
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(
new SimpleGrantedAuthority("ROLE_" + user.getRole().name())
);
}
Example
If the user's role is:
ADMIN
Spring Security internally converts it to:
ROLE_ADMIN
This role will be used during authorization checks.
Step 4: Add Role Information to JWT Token
When generating the JWT token, include the user's role.
Map<String, Object> claims = new HashMap<>();
claims.put("role", user.getRole().name());
String token = jwtService.generateToken(claims, user);
Generated JWT Payload:
{
"sub": "Sulochana",
"role": "ADMIN"
}
Now the role information travels securely with every request.
Step 5: Configure Role-Based Access
Configure Spring Security to restrict API access.
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)
throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**")
.hasRole("ADMIN")
.requestMatchers("/manager/**")
.hasRole("MANAGER")
.requestMatchers("/user/**")
.hasAnyRole("USER", "ADMIN")
.anyRequest()
.authenticated()
);
return http.build();
}
How This Works
ADMIN APIs
.requestMatchers("/admin/**")
.hasRole("ADMIN")
Only ADMIN users can access:
/admin/dashboard
/admin/users
/admin/settings
MANAGER APIs
.requestMatchers("/manager/**")
.hasRole("MANAGER")
Only MANAGER users can access:
/manager/reports
/manager/approvals
USER APIs
.requestMatchers("/user/**")
.hasAnyRole("USER","ADMIN")
Both USER and ADMIN can access:
/user/profile
/user/history
Step 6: Create Protected APIs
Admin Controller
@RestController
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/dashboard")
public String dashboard() {
return "Welcome Admin";
}
}
User Controller
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/profile")
public String profile() {
return "User Profile";
}
}
Testing with Postman
Login as USER
JWT Payload:
{
"username":"Sulochana",
"role":"USER"
}
Access:
GET /user/profile
Result:
200 OK
Access:
GET /admin/dashboard
Result:
403 Forbidden
Common Mistakes
1. Forgetting ROLE_ Prefix
Incorrect:
new SimpleGrantedAuthority("ADMIN")
Correct:
new SimpleGrantedAuthority("ROLE_ADMIN")
2. Not Including Roles in JWT
If roles are not present in the JWT token, authorization checks will fail.
3. Confusing Authentication and Authorization
Authentication:
Who are you?
Authorization:
What are you allowed to do?
4. Using hasRole() Incorrectly
Incorrect:
.hasRole("ROLE_ADMIN")
Correct:
.hasRole("ADMIN")
Spring automatically adds the ROLE_ prefix.
Interview Questions
1. What is RBAC?
RBAC is a security model that grants access to resources based on user roles.
2. What is the difference between Authentication and Authorization?
Authentication verifies identity, while authorization determines permissions.
3. Why do we use ROLE_ prefix in Spring Security?
Spring Security uses ROLE_ as the default prefix for role-based authorities.
4. What is the difference between hasRole() and hasAuthority()?
hasRole():
.hasRole("ADMIN")
Internally becomes:
ROLE_ADMIN
hasAuthority():
.hasAuthority("ROLE_ADMIN")
Requires the full authority name.
5. Why is RBAC important?
RBAC improves security, simplifies permission management, and ensures users can access only authorized resources.
Conclusion :
In this article, we learned how to implement Role-Based Access Control (RBAC) in Spring Security using JWT Authentication. We created roles, secured APIs based on user permissions, included roles inside JWT tokens, and restricted access using Spring Security configuration.
RBAC is one of the most important security concepts used in enterprise applications, banking systems, e-commerce platforms, and microservices architectures.
In the next article, we'll explore Method-Level Security using annotations such as @PreAuthorize, @PostAuthorize, and @Secured. We'll learn how to secure individual service and controller methods and implement fine-grained access control in Spring Boot applications.

Comments
Post a Comment