-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Closed
Labels
status: waiting-for-triageAn issue we've not yet triagedAn issue we've not yet triagedtype: bugA general bugA general bug
Description
Describe the bug
When a @PreAuthorize
annotated method is called with insufficient permissions (anonymous call, missing authorities, missing roles), a AuthorizationDeniedException
is thrown (like with Spring 6) but it is translated into HTTP 500 response when .oauth2ResourceServer
is enabled.
To Reproduce
Execute a request on a path handled by a method decorated with @PreAuthorize
with oauth2ResourceServer
enabled.
@SpringBootApplication
@EnableMethodSecurity
public class DemoApplication {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.oauth2ResourceServer(x -> x.jwt(Customizer.withDefaults()))
//.httpBasic(Customizer.withDefaults())
.build();
}
public static void main(String[] args) {
var ctx = SpringApplication.run(DemoApplication.class, "--spring.security.oauth2.resourceserver.jwt.issuer-uri=http://whatever");
RestClient restClient = RestClient.create();
var resp = restClient.get()
.uri("http://localhost:8080/foo")
.retrieve()
.toBodilessEntity();
}
}
@RestController
class FooEndpoint {
@GetMapping("foo")
@PreAuthorize("isAuthenticated()")
public String foo() {
return "foo";
}
}
It looks like a jakarta.servlet.error.exception
attribute is added to the request. When Tomcat sees that it returns a 500 response with HTML code in the body
Code from org.apache.catalina.valves.ErrorReportValve
(ERROR_EXCEPTION
is jakarta.servlet.error.exception
).
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
// If an async request is in progress and is not going to end once this
// container thread finishes, do not process any error page here.
if (request.isAsync() && !request.isAsyncCompleting()) {
return;
}
if (throwable != null && !response.isError()) {
// Make sure that the necessary methods have been called on the
// response. (It is possible a component may just have set the
// Throwable. Tomcat won't do that but other components might.)
// These are safe to call at this point as we know that the response
// has not been committed.
response.reset();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
Expected behavior
Status 401 or 403, but not 500.
Sample
Metadata
Metadata
Assignees
Labels
status: waiting-for-triageAn issue we've not yet triagedAn issue we've not yet triagedtype: bugA general bugA general bug