-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[WIP] Do not expose routing 404 exception for protected route #11480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Do not merge this yet, I've found a big problem with this PR :) |
*/ | ||
public function testRoutingErrorIsNotExposedForNotExistingProtectedResource($config) | ||
{ | ||
if (strpos(PHP_OS, "WIN") === 0 && version_compare(phpversion(), "5.3.9", "<")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Symfony code usually checks if the OS is Windows using this snippet:
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
// ...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just copied this from the test above this one, should I change it everywhere?
I know this is a difficult issue to solve, but from a user-perspective, I hope this will work out :). |
public function onKernelException(GetResponseForExceptionEvent $event) | ||
{ | ||
$exception = $event->getException(); | ||
if ($exception instanceof HttpException && 404 === $exception->getStatusCode()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you might be able to use Response::HTTP_NOT_FOUND
not found here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The framework normally uses the status codes directly afair.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, sorry for noise
I don't get the purpose of this PR. Currently, when an access control is set on a path that is not defined in the routing it will return a 401 response when trying to access it without the correct permission, instead of a 404? |
@gquemener yes. In a protected area, you should always return a 401. The URL might contain (in some way) sensitive data, so this is a privacy issue. |
If I understand the case correctly, you're effectively trying to change the exception into an access denied based on the URL and permissions. Checking kernel.exception is already too late. What you want to do is change the exception being thrown by the routing if access is denied. |
I'm quite confused here. In that case, I don't see how a 404 could be returned when the firewall detects an unauthorized access. |
It's not about the 404 errors thrown by a controller. When a router can't find a route, it'll throw a 404 causing exception too. Since the firewall is registered after the router (so we can use routes for the login path and such), this exception will be thrown first and the firewall never gets executed. That's why people see the 404 exception. We have to find a way to transform those 404 exceptions into 403 exceptions.
We can't change the routing exception, since the Routing shouldn't do anything with security. And we can't place it before the router, since we loose the ability to use routes then. |
Ah allright, thanks @wouterj, I forgot about this RouterListener. Crazy idea: Forbid to set access_control on route that does not exist. |
That's not going to solve the issue. Assume an access_control like: Assume the admin can edit blog articles. That URL would be something like |
In the example you give, The only case that is not handled correctly today is when setting an access_control with a pattern that doesn't match any route in the application. I'm wondering if it makes sense to set access control with such pattern. Doesn't it mean that one protects access of... well... nothing? |
Then I don't understand what @schmittjoh tried to say in #2679 ... |
I think you clarified very well the issue in #2679 (comment) I'm just concerned about the real use case of defining access rule on pattern that will never be matched against any route in the application. If there's no such use case, then it'll probably be easier to prevent user to configure access rules on invalid route pattern, than trying to convert 404 into 403. |
@gquemener I got it now. If you define an access rule for |
Aaah that's right, that's why my solution is not acceptable! Good catch @wouterj! So, it seems that your solution is quite acceptable then. Let me know if you need some help with "the BIG problem with this PR" 😉 (see #11480 (comment)) |
The problem:
So there is no way we can handle the AccessDeniedException in |
I was having a BrainstormSessionInterface with myself so here we go. At the moment, we rely on an Exception to be thrown when a 404 is triggered. Because an exception is thrown, the What if, instead of throwing an exception, we fire a new event (example:
This solves a couple of things for symfony as you won't have your dependency issue between the routing and security. It will also allow for stronger fallbacks which additionally, for my personal case, we can use our (by symfony2 defined) error pages if symfony1 also goes into 404 because we can still access the proper chain. Right now we listen to kernel.exception which already is going exit in symfony2. As far as I can tell, this is only an internal change. The 404 exception will still be thrown at lowest priority and go into the I hope I managed to make clear what my idea is, if you have any questions, feel free to ask. |
@iltar triggering an event would not prevent other logic from running, while you might not be in a state where you want it to run (and all places wanting to trigger a 404 would then have to be able to return a Response making its way all the way up to the kernel). |
@stof but in this issue, that behaviour is actually desired. You can still throw the 404 exception, this won't be backwards incompatible. The event would also trigger the 404 exception (rather than setting content in the event). The only difference is that using an event, you can hook into it and do some custom checks, for example alter the status from 404 to 403 or 401, without BC breaks. |
@iltar if you register a listener on the |
@wouterj What's the status of this PR? I think it's not worth to invest too much into this. |
@fabpot this can't be done with the current code design. I kept this PR open because there is an interesting discussion going on about how to fix this issue. I think it does make a lot of sense to at least try to fix this before Symfony 3.0. |
@wouterj "this can't be done with the current code design." Sure, that's why I didn't fix it by then. So, closing now. |
I'm not sure if this is seen as a new feature or as a bug fix, so I just
submitted it to the master branch.