Problem/Motivation
While working on #2737719: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method, I encountered 403 responses when I expected to get 406 responses. Let me quote #2737719-38: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method, which is where this is being reported:
The struggle is because of the weird interaction/design of the routing + authentication system, which causes things to fail miserably in an unfriendly way when the user forgets to specify
?_format=nonsense, or has a typo (for example?_format=haljsonon a URL that already has a HTML route.It's very very very confusing how Symfony's routing system first grants access because a user is authenticated via basic auth, and so
AccessAwareRoutersays everything is okay, and then afterwards, duringAuthenticationSubscriber::onKenrelRequestFilterProvider(), we choose to deny access after all becausebasic_authisn't a globally allowed access provider, and the matched route (which matches the HTML, non-REST route due to the missing?format=) is lacking an_authroute option. You can either get a 406 (which is what we want), or a 403 with HTML (in case of non-specified or invalid format) or a 403 in the expected format (in case of non-specified or invalid format plusAcceptheader, even though we don't actually supportAcceptheaders… thanks toDefaultExceptionSubscribercallingRequest::getAcceptableContentTypes()).
Worse, it's even possible to get the appropriate 406 response in case of an invalid format, but for that response to be sent withContent-Type: text/html! (In case of anonymous.)More edge cases than I can count.
Seems like the authentication system and routing system are integrated in a brittle, confusing, backward manner. And the content negotiation system makes it that tiny bit extra unpredictable. This is no one's fault. This is complex software with (too) many layers, and without comprehensive integration tests, this sort of thing is to be expected.
Proposed resolution
TBD
Remaining tasks
- Determine root cause.
- Propose possible solutions
- TBD
User interface changes
None.
API changes
TBD, hopefully none.
Data model changes
TBD, hopefully none.
| Comment | File | Size | Author |
|---|---|---|---|
| #24 | 2805279-24.patch | 7.7 KB | wim leers |
| #24 | interdiff.txt | 821 bytes | wim leers |
| #23 | 2805279-23.patch | 7.7 KB | wim leers |
| #18 | 2805279-18-interdiff.txt | 3.43 KB | cburschka |
| #18 | 2805279-18.patch | 7.74 KB | cburschka |
Comments
Comment #3
wim leersThis is the pretty crazy assertion that is called 4 times by
EntityResourceTestBase:It was added in #2737719: EntityResource: Provide comprehensive test coverage: for every entity type, every format, every method.
That's the assertion that this issue should remove.
Comment #4
wim leersSomewhat related: #2817727: Add test coverage to prove controller is called *after* authentication validation.
Comment #6
dawehnerI started to experiment with something like this, but its certainly not a proper solution yet.
Comment #7
wim leersThanks for getting this started!
I'll provide a patch from the other direction: per #3, this is the test simplification we should be able to make, which should fail against HEAD, and which the patch we develop here should allow to pass tests.
Comment #8
wim leersComment #9
dawehnerYeah, collaboration: 🎆
Comment #12
dawehner#6 had a missing file ...
Comment #13
wim leersAnd #12 was never queued for testing :P Very high probability this no longer applies.
Comment #15
cburschkaConflict resolved...
Comment #17
cburschkaIt looks like all of the test failures result from the test class still expecting 403 instead of 406, so that should be fine once it is updated.
Comment #18
cburschkaRemoving the @todo-marked function and replacing the calls.
Comment #20
wim leersThanks for pushing this forward, @cburschka!
Comment #22
wim leersSee #2854543-28: NegotiationMiddleware calls $request->setRequestFormat('html') when there is no _format request parameter, but shouldn't and #2854543-30: NegotiationMiddleware calls $request->setRequestFormat('html') when there is no _format request parameter, but shouldn't — that issue is starting to cross over into the territory/scope of this issue.
Comment #23
wim leers#2854543: NegotiationMiddleware calls $request->setRequestFormat('html') when there is no _format request parameter, but shouldn't landed. Let's see what happens if we run tests again the latest patch (#18) from almost 7 months ago…
This needed to be rebased, because #2854543: NegotiationMiddleware calls $request->setRequestFormat('html') when there is no _format request parameter, but shouldn't shifted some of the test assertions around. diffstat is nearly identical.
Comment #24
wim leersIt seems this change is necessary in the assertions for tests to pass.
Comment #36
g-brodieiAdding new tags for steps to reproduce and requires summary update for new contributors to step in easier.