Can I check if the URL / route behind the firewall is protected programmatically?

I have a situation where I need to run some code if the user is trying to access a secure URL and is not authenticated / authorized.

By default, Symfony processes unauthorized users by redirecting or forwarding the user to the login form. I would like this to not happen if the request method is POST, and instead a JSON echo object.

The best way I can handle this is to create a custom listener that listens to the kernel.request event and checks for two things:

  • checks if a POST request method
  • checks if the user is fully authenticated

If this is a POST request and the user is not fully authenticated, I would highlight the JSON object.

But my listener (as expected) fires for all requests - I would like to limit it to only checking if the request is for a URL protected by a firewall. Can this be checked programmatically?

I also have suspicious suspiciousness, there is an easier way to do this, but I can’t understand it, so if anyone has any tips, I would like to hear them :)

Edit
@Problematic. The reason for checking only the firewall requests is that I have some requests that are not a firewall, and if my code is running, I get the above JSON object instead of the actual request response.

Right now, if I have not logged in and have not executed the POST request for api/get/something (which is located behind the firewall), Symfony returns an HTML describing the login page. Instead, I just want to repeat something like {error: 'User is not authorized'} . But I want this to happen only for POST requests.

+6
source share
1 answer

I think I was wrong. I wanted to know if the URL was behind the firewall, but I think I should have known if the current user was allowed for the request. In fact, knowing that the user is denied access to the URL means that the URL must be behind the firewall, otherwise access could not be denied.

With this in mind, I was able to get the final result that I wanted. It's pretty simple once you understand how the security mechanism works ...

  • Symfony\Component\Security\Http\Firewall listens for the kernel.request event
  • The firewall then calls several event listeners registered in security.yml
  • If a security violation is detected (i.e. a user trying to access something without logging in), an AccessDeniedException and a kernel.exception event is kernel.exception .
  • Symfony/Component/Security/Http/Firewall/ExceptionListener listens for the event and fires its onKernelException method, which determines what the next step is. In my case, it will start the authentication process

Since starting the authentication process is something I wanted to avoid, I wrote my own event listener that catches kernel.exception before the Symfony ExceptionListener does. I gave my event listener priority 1.

This is the method I wrote:

 public function handleException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); $request = $event->getRequest(); if ($request->getMethod() == 'POST') { if ($exception instanceof AccessDeniedException) { $response = new Response({err: 'not logged in'}); $event->setResponse($response); } } } 

Until the user is logged in and the request method is POST, a JSON object is returned (which also stops the event being positioned) instead of HTML for the login page. Otherwise, other kernel.exception listeners will respond, and Symfony can go about its business.

So, the original question remains unanswered, but I think this can be achieved by checking if the user has access to the action. Symfony\Component\Security\Core\Authorization\AccessDecisionManager looks like this would be useful for this.

Edit
I do not know if this method only processes users who are not logged in. I have not tested it yet, but I think that it also works if the user (login) tries to access an action that requires a role that they provide was not. If this causes a problem, I will try to change it to use the Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver isFullFledged($token) method to take care only of users who are not logged in.

+3
source

Source: https://habr.com/ru/post/899244/


All Articles