Springboot version 2.3.4.RELEASE
Jetty version jetty-9.4.31.v20200723; built: 2020-07-23T17:57:36.812Z; git: 450ba27947e13e66baa8cd1ce7e85a4461cacc1d; jvm 15+36-1562 Java version OpenJDK Runtime Environment (build 15+36-1562) OS type/version Windows 10 Description
Hi,
first of all I'm not sure if this is Jetty issue or spring.
I have bearer protected app. I have set Multipart max file size and max request size to 10mb.
MultipartConfigFactory factory = new MultipartConfigFactory();
factory.setMaxFileSize(DataSize.ofMegabytes(10));
factory.setMaxRequestSize(DataSize.ofMegabytes(10));
return factory.createMultipartConfig();
Authorization header is correctly set as everything works for files under the limit.
But when I try to upload a file bigger than that jetty (correctly) throws exception
if (MultiPartInputStreamParser.this._config.getMaxFileSize() > 0 && _size + 1 > MultiPartInputStreamParser.this._config.getMaxFileSize())
throw new IllegalStateException("Multipart Mime part " + _name + " exceeds max filesize");
This later gets mapped to BadMessageException
org.eclipse.jetty.server.HttpChannel [qtp765329253-31] handleException /my-path org.eclipse.jetty.http.BadMessageException: 400: Unable to parse form content
I would expect 400 code here as I need to notify client that he tried to upload too big file.
But the app returns 401 Unauthorized. This jetty exception happens when BearerTokenAuthenticationFilter calls DefaultBearerTokenResolver.resolve.
BearerTokenAuthenticationEntryPoint receives authException InsufficientAuthenticationException "Full authentication is required to access this resource" hence 401.
401 is wrong, seems like jetty exception leads to failure to obtain Authorization header.
My guess this is bug on spring. Any workaround this so I would return 400 in case of BadMessageException?
Comment From: eleftherias
Thanks for reaching out @MatCuk. Can you provide a minimal sample that reproduces this issue?
Comment From: MatCuk
Checkout: https://github.com/MatCuk/spring-issue-9181
In postman select POST to localhost:8080/upload
If you select file bigger than 10mb you get 401.
Comment From: eleftherias
Thanks for the sample @MatCuk.
Looking at the logs I see that Jetty is performing an error dispatch when the file size exceeds the max.
Logs:
2020-11-16 17:27:38.450 DEBUG 48926 --- [tp1934729582-45] org.eclipse.jetty.server.session : Entering scope org.eclipse.jetty.server.session.SessionHandler475024998==dftMaxIdleSec=1800, dispatch=ERROR asyncstarted=false
2020-11-16 17:27:38.450 DEBUG 48926 --- [tp1934729582-45] org.eclipse.jetty.server.session : sessionHandler=org.eclipse.jetty.server.session.SessionHandler475024998==dftMaxIdleSec=1800 session=null
2020-11-16 17:27:38.450 DEBUG 48926 --- [tp1934729582-45] o.eclipse.jetty.servlet.ServletHandler : servlet |/error|null -> dispatcherServlet@7ef5559e==org.springframework.web.servlet.DispatcherServlet,jsp=null,order=-1,inst=true,async=true
This causes it to try to access the "/error" page which is secured and therefore you see a 401 response.
One solution is to permit access to the "/error" page, assuming that there is no sensitive information on there.
http.authorizeRequests(authorize -> authorize
.antMatchers("/error").permitAll()
.anyRequest().authenticated()
)
// ...
Based on this issue, I have also created gh-9205, which will allow you to define what security rules apply on an error dispatch.
Comment From: MatCuk
Ok, will try. Thanks!
Comment From: MatCuk
Can confirm it works now.