Backend Projects
7/20/2026
4 min read

Mastering Spring Security 7 with Spring Boot 4 and Java 21 – Part 5: Roles vs Authorities Explained

Mastering Spring Security 7 with Spring Boot 4 and Java 21 – Part 5: Roles vs Authorities Explained

In the previous article, we implemented database authentication using a custom UserDetailsService and Spring Data JPA.

Authentication answers the question:

"Who is the user?"

However, once a user is authenticated, the application still needs to determine what resources that user can access. This is where authorization becomes essential.

Many beginners believe that roles alone are sufficient for access control. While roles work well for smaller applications, enterprise systems often require fine-grained permissions. Instead of granting broad access based on a role, permissions allow precise control over specific actions.

In this article, we will explore role-based and authority-based authorization in Spring Security 7, understand their differences, and implement production-ready access control for REST APIs.

What is Authorization?

Authorization is the process of determining whether an authenticated user has permission to access a resource or perform an action.

For example:

  • A customer can view products.

  • A warehouse employee can update inventory.

  • An administrator can manage users.

  • A finance manager can generate reports.

All of these users may be authenticated successfully, but each has different permissions.

Understanding Roles

A role is a collection of permissions assigned to a user.

Examples:

ROLE_USER
ROLE_ADMIN
ROLE_MANAGER
ROLE_SUPER_ADMIN

Roles make user management easier because permissions can be grouped together.

Example:

Role

Permissions

USER

View Products

ADMIN

Manage Products, Manage Users

MANAGER

View Reports, Update Inventory

Understanding Authorities

Authorities represent individual permissions.

Examples:

READ_PRODUCTS
CREATE_PRODUCTS
UPDATE_PRODUCTS
DELETE_PRODUCTS

READ_USERS
CREATE_USERS
DELETE_USERS

VIEW_REPORTS

Instead of asking whether someone is an administrator, Spring Security checks whether they possess the required permission.

This provides much greater flexibility.

Roles vs Authorities

Roles

Authorities

Broad access

Fine-grained access

Easier to manage

More flexible

Suitable for small projects

Suitable for enterprise systems

Example: ADMIN

Example: DELETE_PRODUCTS

In production systems, roles usually contain multiple authorities.

Example:

ROLE_ADMIN

READ_PRODUCTS
CREATE_PRODUCTS
UPDATE_PRODUCTS
DELETE_PRODUCTS

READ_USERS
CREATE_USERS
DELETE_USERS

Real-World Example

Consider an E-Commerce Platform.

Customer

Permissions:

  • Browse products

  • Place orders

  • Track shipments

Seller

Permissions:

  • Add products

  • Update inventory

  • View orders

Administrator

Permissions:

  • Manage users

  • Manage products

  • Generate reports

  • View system logs

Instead of checking only for the ADMIN role, the application checks whether the user has the required authority.

Using Roles

Spring Security provides the hasRole() method.

.requestMatchers("/admin/**")
.hasRole("ADMIN")

Only users with the ROLE_ADMIN role can access these APIs.

Internally, Spring Security automatically adds the ROLE_ prefix.

Therefore:

.hasRole("ADMIN")

actually checks:

ROLE_ADMIN

Using Authorities

Spring Security also provides hasAuthority().

.requestMatchers("/products/create")
.hasAuthority("CREATE_PRODUCTS")

Now access depends on a permission rather than a role.

This approach is more flexible because multiple roles can share the same authority.

Using Multiple Roles

.requestMatchers("/dashboard")
.hasAnyRole("ADMIN","MANAGER")

Both administrators and managers can access the dashboard.

Using Multiple Authorities

.requestMatchers("/reports")
.hasAnyAuthority(
"VIEW_REPORTS",
"DOWNLOAD_REPORTS")

A user possessing either permission can access the endpoint.

Security Configuration Example

@Bean
publicSecurityFilterChainsecurityFilterChain(HttpSecurityhttp)
throws Exception {

returnhttp
.csrf(AbstractHttpConfigurer::disable)

.authorizeHttpRequests(auth ->auth

.requestMatchers("/public/**")
.permitAll()

.requestMatchers("/admin/**")
.hasRole("ADMIN")

.requestMatchers("/products")
.hasAuthority("READ_PRODUCTS")

.requestMatchers("/products/create")
.hasAuthority("CREATE_PRODUCTS")

.requestMatchers("/reports")
.hasAnyRole("ADMIN","MANAGER")

.anyRequest()
.authenticated())

.httpBasic(Customizer.withDefaults())

.build();
}

Creating Authorities

Instead of:

ROLE_ADMIN

We can assign:

READ_PRODUCTS
CREATE_PRODUCTS
UPDATE_PRODUCTS
DELETE_PRODUCTS

READ_USERS
UPDATE_USERS
DELETE_USERS

VIEW_REPORTS

The administrator receives all permissions.

Managers receive only reporting permissions.

Customers receive only product viewing permissions.

Converting Database Roles into Authorities

Suppose the database stores:

Username

Role

john

USER

admin

ADMIN

During authentication:

returnUser.builder()
.username(user.getUsername())
.password(user.getPassword())
.roles(user.getRole())
.build();

Spring Security converts these roles into granted authorities.

Using GrantedAuthority

Every permission inside Spring Security is represented by a GrantedAuthority.

Example:

Collection<GrantedAuthority>authorities=
List.of(

newSimpleGrantedAuthority("READ_PRODUCTS"),

newSimpleGrantedAuthority("CREATE_PRODUCTS")

);

These authorities are stored inside the authenticated user.

Whenever an endpoint is accessed, Spring Security compares the required permission with the user's granted authorities.

Real-World Enterprise Example

Imagine a Hospital Management System.

Doctor

Permissions:

READ_PATIENTS
UPDATE_PATIENTS
CREATE_PRESCRIPTIONS

Receptionist

Permissions:

CREATE_PATIENT
VIEW_APPOINTMENTS

Administrator

Permissions:

CREATE_USERS
DELETE_USERS
VIEW_REPORTS
SYSTEM_CONFIGURATION

Instead of creating dozens of roles, permissions provide precise access control.

Common Mistakes

Using Roles for Everything

Small applications can rely on roles.

Large enterprise applications should use authorities.

Hardcoding Permissions

Avoid scattering permission names throughout the codebase.

Instead, create constants.

publicclassPermissions {

publicstaticfinalString
READ_PRODUCTS="READ_PRODUCTS";

}

Giving Everyone ADMIN

Grant only the permissions required for a user's responsibilities.

Follow the Principle of Least Privilege.

Mixing Business Logic with Authorization

Controllers should focus on business operations.

Authorization rules should remain inside the security configuration or method-level annotations.

Production-Level Best Practices

Prefer Authorities for Large Applications

Authorities provide greater flexibility and scalability.

Use RBAC with Fine-Grained Permissions

A common enterprise model:

User

↓

Role

↓

Authorities

↓

API Access

Store Permissions in Database

Instead of hardcoding permissions, maintain them in dedicated tables.

Example:

users

roles

permissions

user_roles

role_permissions

This allows administrators to manage permissions without changing code.

Audit Permission Changes

Record every role assignment and permission modification.

This improves traceability and security.

Avoid Duplicate Permissions

Create reusable permission definitions shared across multiple roles.

Tags

Enjoyed this article?

Subscribe to our newsletter for more backend engineering insights and tutorials.