🔥 Launch Offer: Interview Preparation Bundle @ ₹2,499 ₹9,999 • 75% OFF. Offer expires in 🔥 Launch Offer: Interview Preparation Bundle @ ₹2,499 ₹9,999 • 75% OFF. Offer expires in Interview Preparation Bundle @ ₹2,499 ₹9,999

00:00:00 Get Bundle
home spring boot why-do-we-need-preauthorize-when-we-already-have-securityfilterchain-in-spring-security
Interview guide Spring Boot 19 sections

Why Do We Need @PreAuthorize When We Already Have SecurityFilterChain in Spring Security?

One of the most common Spring Security interview questions is: "If we can secure endpoints using SecurityFilterChain, then why do we need @PreAuthorize?" At first, it seems like…

Start reading
By javainterviewprep June 12, 2026 6 min read

One of the most common Spring Security interview questions is:

“If we can secure endpoints using SecurityFilterChain, then why do we need @PreAuthorize?”

At first, it seems like both solve the same problem. After all, SecurityFilterChain already authenticates users and authorizes them based on roles.

So why introduce another authorization mechanism?

The answer lies in understanding the difference between URL-level security and business-level security.

Let’s understand this with real-world examples.


Understanding SecurityFilterChain

Suppose we have an e-commerce application.

There are two types of users:

  • ADMIN
  • CUSTOMER

We configure Spring Security as follows:

@Bean
SecurityFilterChain security(HttpSecurity http) throws Exception {

    http.authorizeHttpRequests(auth -> auth
            .requestMatchers("/admin/**").hasRole("ADMIN")
            .requestMatchers("/orders/**").hasAnyRole("ADMIN", "CUSTOMER")
            .anyRequest().authenticated());

    return http.build();
}

Now every request passes through Spring Security.

If a user tries to access

/admin/**

only ADMIN is allowed.

If a user accesses

/orders/**

both ADMIN and CUSTOMER are allowed.

This is called URL-level authorization.

Spring Security simply checks:

  • Is the user authenticated?
  • Does the user have the required role?

If yes, the request proceeds to the controller.

For many applications, this is completely sufficient.


Does This Mean We Never Need @PreAuthorize?

Not necessarily.

If your authorization depends only on URLs and roles, then SecurityFilterChain is enough.

For example,

/admin/**

→ ADMIN

/customer/**

→ CUSTOMER

No additional authorization is required.

This is why many small applications never use @PreAuthorize.


Then Why Was @PreAuthorize Introduced?

The problem starts when authorization depends on business rules, not just the URL.

Let’s understand this with an e-commerce example.


E-commerce Example

Suppose we have an API to cancel an order.

DELETE /orders/{orderId}

Both ADMIN and CUSTOMER are allowed to access this endpoint.

So our SecurityFilterChain looks like this:

.requestMatchers("/orders/**")
.hasAnyRole("ADMIN", "CUSTOMER")

Everything looks correct.

Now imagine the following data.

Order IDOwner
1001Alice
1002Bob
1003Charlie

Bob logs into the application.

The frontend shows only Bob’s orders.

There is no Cancel button for Alice’s order.

So many developers think,

“Since the UI only shows Bob’s orders, there is no problem.”

Unfortunately, this assumption is wrong.


The Frontend Is Not a Security Boundary

A browser is only one client.

A user can completely ignore your frontend.

For example, Bob can open Postman and send

DELETE /orders/1001

or use curl

curl -X DELETE \
http://localhost:8080/orders/1001

with his valid JWT token.

He never used your frontend.

He directly called your API.


What Does SecurityFilterChain Check?

Spring Security sees:

URL = /orders/1001

Role = CUSTOMER

It checks

Can CUSTOMER access /orders/** ?

Answer:

Yes

So the request reaches the controller.

Notice something important.

Spring Security does not know

  • Who owns Order 1001
  • Whether Bob owns this order
  • Whether Bob is allowed to cancel it

It only knows

Role = CUSTOMER

This is where URL-level authorization reaches its limit.


Business Rules Cannot Be Expressed Using URLs

Our actual business rule is

  • ADMIN can cancel any order.
  • CUSTOMER can cancel only their own order.

This rule has nothing to do with URLs.

Instead, it depends on business data stored in the database.

SecurityFilterChain cannot query the database and compare ownership.

This is where @PreAuthorize becomes useful.


Using @PreAuthorize

@Service
public class OrderService {

    @PreAuthorize(
        "hasRole('ADMIN') || @orderSecurity.isOwner(#orderId)"
    )
    public void cancelOrder(Long orderId) {

        // Cancel order

    }

}

Now Spring performs another check before executing the method.

If the user is ADMIN,

access is immediately granted.

Otherwise,

Spring calls

@Component
public class OrderSecurity {

    @Autowired
    private OrderRepository repository;

    public boolean isOwner(Long orderId) {

        String loggedInUser =
            SecurityContextHolder.getContext()
                    .getAuthentication()
                    .getName();

        Order order =
            repository.findById(orderId)
                    .orElseThrow();

        return order.getCustomerUsername()
                .equals(loggedInUser);
    }

}

Now authorization depends on actual business data.


What Happens Now?

Scenario 1

Alice logs in.

Calls

DELETE /orders/1001

Database says

Owner = Alice

Logged-in user

Alice

Result

Allowed

Scenario 2

Bob logs in.

Calls

DELETE /orders/1001

Database says

Owner = Alice

Logged-in user

Bob

Result

AccessDeniedException

The order is never cancelled.


Scenario 3

Admin logs in.

Calls

DELETE /orders/1001

Since

hasRole("ADMIN")

returns true,

ownership is not even checked.

Admin can cancel any order.


Can’t We Implement This Using SecurityFilterChain?

This is another interview question.

The answer is No.

SecurityFilterChain works at the HTTP request level.

It mainly knows

  • Request URL
  • HTTP Method
  • Authentication
  • Authorities

It does not know

  • Order owner
  • Product owner
  • Employee department
  • Loan amount
  • Business status
  • Database values

Those are business concepts.

Business authorization belongs inside the service layer.


A Common Misconception

Many beginners say,

“The frontend only shows the customer’s own orders, so another customer’s order cannot be cancelled.”

This is incorrect.

The frontend is only a user interface.

Anyone can bypass it using

  • Postman
  • curl
  • Swagger
  • Mobile apps
  • Custom scripts

Security should always be enforced by the backend.

A famous security principle says:

Never trust the client. Trust only the server.


So When Is SecurityFilterChain Enough?

If authorization depends only on roles and URL patterns.

Example:

/admin/**

→ ADMIN

/customer/**

→ CUSTOMER

/public/**

→ Everyone

In such cases,

there is no need for @PreAuthorize.


When Should You Use @PreAuthorize?

Use @PreAuthorize whenever authorization depends on business logic.

Examples include:

  • Customer can access only their own order.
  • Employee can view only employees from their department.
  • Manager can approve leave only for their team.
  • Loan manager can approve loans below ₹50,000.
  • Product seller can update only their own products.
  • Doctor can access only assigned patients.

All of these require database checks or method parameters.

These cannot be expressed using simple URL matching.


SecurityFilterChain vs @PreAuthorize

SecurityFilterChain@PreAuthorize
Works at URL levelWorks at method level
Checks authenticationChecks business rules
Checks rolesChecks roles, ownership, permissions and custom logic
Best for coarse-grained authorizationBest for fine-grained authorization
No database lookupCan execute custom business logic

Interview Answer

Interviewer: Why do we need @PreAuthorize if we already have SecurityFilterChain?

Answer:

“SecurityFilterChain performs coarse-grained authorization by protecting URLs based on roles or authorities. It is ideal when access depends only on the endpoint. However, many real-world applications require fine-grained authorization based on business rules such as resource ownership, order status, department, or permissions stored in the database. SecurityFilterChain cannot evaluate these business conditions. @PreAuthorize allows us to execute custom authorization logic before the service method runs, ensuring that only authorized users can perform specific business operations.”


Final Thoughts

SecurityFilterChain and @PreAuthorize are not competitors. They solve different problems.

Use SecurityFilterChain as the first line of defense to authenticate users and protect endpoints.

Use @PreAuthorize to enforce business-specific authorization rules that cannot be represented using URL patterns alone.

In enterprise applications, both are commonly used together to build a secure and maintainable authorization model.