spring-projects / spring-projects/spring-security

WebInvocationPrivilegeEvaluator throws UnsupportedOperationException when a dispatcherTypeMatcher is configured.

Open
#19,131 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: bug
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Describe the bug

We are using a WebInvocationPrivilegeEvaluator to evaluate if a user has access to some paths.
After upgrading Spring Security from 6.5.10 to 7.0.4, this now throws a java.lang.UnsupportedOperationException.

To Reproduce

Configure some dispatcherTypeMatcher in your HttpSecurity.
For instance:

httpSecurity.authorizeHttpRequests(authorizedRequests -> 
    authorizedRequests.dispatcherTypeMatchers(DispatcherType.ERROR, DispatcherType.FORWARD)
                      .permitAll());

Create a controller, and let Spring inject a WebInvocationPrivilegeEvaluator bean:

@RestController
@RequestMapping("/check-access")
public class MyController {

  private final WebInvocationPrivilegeEvaluator privilegeEvaluator;

  @Autowired
  public MyController(WebInvocationPrivilegeEvaluator aPrivilegeEvaluator) {
    privilegeEvaluator = aPrivilegeEvaluator;
  }

  @GetMapping("/anonymous")
  public boolean checkAnonymousAccess() {
      return privilegeEvaluator.isAllowed("/foo", new AnonymousAuthenticationToken("anonymous", "anonymous", List.of()));
  }
}

Expected behavior

A working check that validates if the path is allowed according to the configured access rules in the HttpSecurity bean.

Actual behavior

java.lang.UnsupportedOperationException: public abstract jakarta.servlet.DispatcherType jakarta.servlet.ServletRequest.getDispatcherType() is not supported
	at org.springframework.security.web.FilterInvocation$UnsupportedOperationExceptionInvocationHandler.invoke(FilterInvocation.java:332)
	at jdk.proxy3/jdk.proxy3.$Proxy241.getDispatcherType(Unknown Source)
	at jakarta.servlet.ServletRequestWrapper.getDispatcherType(ServletRequestWrapper.java:438)
	at jakarta.servlet.ServletRequestWrapper.getDispatcherType(ServletRequestWrapper.java:438)
	at org.springframework.security.web.util.matcher.DispatcherTypeRequestMatcher.matches(DispatcherTypeRequestMatcher.java:72)
	at org.springframework.security.web.util.matcher.RequestMatcher.matcher(RequestMatcher.java:49)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:75)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:52)
	at org.springframework.security.authorization.ObservationAuthorizationManager.authorize(ObservationAuthorizationManager.java:75)
	at org.springframework.security.config.annotation.web.builders.WebSecurity.lambda$addAuthorizationManager$2(WebSecurity.java:384)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:82)
	at org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager.authorize(RequestMatcherDelegatingAuthorizationManager.java:52)
	at org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.isAllowed(AuthorizationManagerWebInvocationPrivilegeEvaluator.java:62)
	at org.springframework.security.web.access.AuthorizationManagerWebInvocationPrivilegeEvaluator.isAllowed(AuthorizationManagerWebInvocationPrivilegeEvaluator.java:54)
	at org.springframework.security.web.access.RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.isAllowed(RequestMatcherDelegatingWebInvocationPrivilegeEvaluator.java:82)
	at com.test.MyController.checkAnonymousAccess(Unknown Source)

Evaluation

The reason this worked with Spring Security 6.5.10 is that in that version, the HandlerMappingIntrospectorRequestTransformer is used to transform the request. That transformer returns a CacheableRequestWrapper that always returns REQUEST as DispatcherType. In Spring Security 7.0.4, this class no longer exist and the DispatcherType is retrieved from the FilterInvocation.DummyRequest class, which throws an UnsupportedOperationException.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with AuthorizationManagerWebInvocationPrivilegeEvaluator, RequestMatcherDelegatingWebInvocationPrivilegeEvaluator, and FilterInvocation.DummyRequest, then reproduce the dispatcherTypeMatchers case from the issue. Trace how the request is transformed before DispatcherTypeRequestMatcher runs; done means WebInvocationPrivilegeEvaluator no longer throws and correctly evaluates the configured access rules.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.