Skip to content
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

Security + JSON_LOGIN return an HTTP 500 instead of an HTTP 403 #25806

Closed
Rebolon opened this issue Jan 16, 2018 · 20 comments
Closed

Security + JSON_LOGIN return an HTTP 500 instead of an HTTP 403 #25806

Rebolon opened this issue Jan 16, 2018 · 20 comments

Comments

@Rebolon
Copy link

Rebolon commented Jan 16, 2018

Q A
Bug report? yes
Feature request? no
BC Break report? no
RFC? no
Symfony version 4.0.3

I'm using the Security component with the (marked as experimental) json_login system that has been introduced in Symfony 3.3

It works quite well, but when i access a route protected by this firewall i get a 500 Symfony\Component\Security\Core\Exception\InsufficientAuthentificationException coming from an Symfony\Component\Security\Core\Exception\AccessDeniedException whereas i expect to get a 403 HTTPException (or something like this).

I've looked at the web and finally i'm looking at the source code. I can see that json_login can expect a failure_handler config but when i follow the official documentation i got a 500 with a json string :

{
  type: "https://tools.ietf.org/html/rfc2616#section-10",
  title: "An error occurred",
  detail: "Type error: Argument 1 passed to Symfony\Component\Security\Http\Authentication\CustomAuthenticationFailureHandler::__construct() must implement interface Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface, instance of App\Security\AccessDeniedHandler given, called in C:\dev\projects\fiducial\sf-flex-encore-vuejs\var\cache\dev\ContainerOkj7dm8\getSecurity_Authentication_Listener_Json_VuejsService.php on line 8",
  trace: [
    {
      namespace: "",
      short_class: "",
      class: "",
      type: "",
      function: "",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\security\Http\Authentication\CustomAuthenticationFailureHandler.php",
      line: 28,
      args: [ ]
    },
    {
      namespace: "Symfony\Component\Security\Http\Authentication",
      short_class: "CustomAuthenticationFailureHandler",
      class: "Symfony\Component\Security\Http\Authentication\CustomAuthenticationFailureHandler",
      type: "->",
      function: "__construct",
      file: "/dev/projects/sf-flex-encore-vuejs/var\cache\dev\ContainerOkj7dm8\getSecurity_Authentication_Listener_Json_VuejsService.php",
      line: 8,
      args: [
        [
          "object",
          "App\Security\AccessDeniedHandler"
        ],
        [
          "array",
          [ ]
        ]
      ]
    },
    {
      namespace: "",
      short_class: "",
      class: "",
      type: "",
      function: "require",
      file: "/dev/projects/sf-flex-encore-vuejs/var\cache\dev\ContainerOkj7dm8\srcDevDebugProjectContainer.php",
      line: 162,
      args: [
        [
          "string",
          "/dev/projects/sf-flex-encore-vuejs/var\cache\dev\ContainerOkj7dm8\getSecurity_Authentication_Listener_Json_VuejsService.php"
        ]
      ]
    },
    {
      namespace: "ContainerOkj7dm8",
      short_class: "srcDevDebugProjectContainer",
      class: "ContainerOkj7dm8\srcDevDebugProjectContainer",
      type: "->",
      function: "load",
      file: "/dev/projects/sf-flex-encore-vuejs/var\cache\dev\ContainerOkj7dm8\getSecurity_Firewall_Map_Context_VuejsService.php",
      line: 12,
      args: [
        [
          "string",
          "/dev/projects/sf-flex-encore-vuejs/var\cache\dev\ContainerOkj7dm8/getSecurity_Authentication_Listener_Json_VuejsService.php"
        ]
      ]
    },
    {
      namespace: "ContainerOkj7dm8",
      short_class: "srcDevDebugProjectContainer",
      class: "ContainerOkj7dm8\srcDevDebugProjectContainer",
      type: "->",
      function: "{closure}",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\security-bundle\Debug\TraceableFirewallListener.php",
      line: 33,
      args: [ ]
    },
    {
      namespace: "Symfony\Bundle\SecurityBundle\Debug",
      short_class: "TraceableFirewallListener",
      class: "Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener",
      type: "->",
      function: "handleRequest",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\security\Http\Firewall.php",
      line: 56,
      args: [
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ],
        [
          "object",
          "Symfony\Component\DependencyInjection\Argument\RewindableGenerator"
        ]
      ]
    },
    {
      namespace: "Symfony\Component\Security\Http",
      short_class: "Firewall",
      class: "Symfony\Component\Security\Http\Firewall",
      type: "->",
      function: "onKernelRequest",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\security-bundle\EventListener\FirewallListener.php",
      line: 48,
      args: [
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ]
      ]
    },
    {
      namespace: "Symfony\Bundle\SecurityBundle\EventListener",
      short_class: "FirewallListener",
      class: "Symfony\Bundle\SecurityBundle\EventListener\FirewallListener",
      type: "->",
      function: "onKernelRequest",
      file: null,
      line: null,
      args: [
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ],
        [
          "string",
          "kernel.request"
        ],
        [
          "object",
          "Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher"
        ]
      ]
    },
    {
      namespace: "",
      short_class: "",
      class: "",
      type: "",
      function: "call_user_func",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\event-dispatcher\Debug\WrappedListener.php",
      line: 104,
      args: [
        [
          "array",
          [
            [
              "object",
              "Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener"
            ],
            [
              "string",
              "onKernelRequest"
            ]
          ]
        ],
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ],
        [
          "string",
          "kernel.request"
        ],
        [
          "object",
          "Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher"
        ]
      ]
    },
    {
      namespace: "Symfony\Component\EventDispatcher\Debug",
      short_class: "WrappedListener",
      class: "Symfony\Component\EventDispatcher\Debug\WrappedListener",
      type: "->",
      function: "__invoke",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\event-dispatcher\EventDispatcher.php",
      line: 212,
      args: [
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ],
        [
          "string",
          "kernel.request"
        ],
        [
          "object",
          "Symfony\Component\EventDispatcher\EventDispatcher"
        ]
      ]
    },
    {
      namespace: "Symfony\Component\EventDispatcher",
      short_class: "EventDispatcher",
      class: "Symfony\Component\EventDispatcher\EventDispatcher",
      type: "->",
      function: "doDispatch",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\event-dispatcher\EventDispatcher.php",
      line: 44,
      args: [
        [
          "array",
          [
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ],
            [
              "object",
              "Symfony\Component\EventDispatcher\Debug\WrappedListener"
            ]
          ]
        ],
        [
          "string",
          "kernel.request"
        ],
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ]
      ]
    },
    {
      namespace: "Symfony\Component\EventDispatcher",
      short_class: "EventDispatcher",
      class: "Symfony\Component\EventDispatcher\EventDispatcher",
      type: "->",
      function: "dispatch",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\event-dispatcher\Debug\TraceableEventDispatcher.php",
      line: 139,
      args: [
        [
          "string",
          "kernel.request"
        ],
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ]
      ]
    },
    {
      namespace: "Symfony\Component\EventDispatcher\Debug",
      short_class: "TraceableEventDispatcher",
      class: "Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher",
      type: "->",
      function: "dispatch",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\http-kernel\HttpKernel.php",
      line: 125,
      args: [
        [
          "string",
          "kernel.request"
        ],
        [
          "object",
          "Symfony\Component\HttpKernel\Event\GetResponseEvent"
        ]
      ]
    },
    {
      namespace: "Symfony\Component\HttpKernel",
      short_class: "HttpKernel",
      class: "Symfony\Component\HttpKernel\HttpKernel",
      type: "->",
      function: "handleRaw",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\http-kernel\HttpKernel.php",
      line: 66,
      args: [
        [
          "object",
          "Symfony\Component\HttpFoundation\Request"
        ],
        [
          "integer",
          1
        ]
      ]
    },
    {
      namespace: "Symfony\Component\HttpKernel",
      short_class: "HttpKernel",
      class: "Symfony\Component\HttpKernel\HttpKernel",
      type: "->",
      function: "handle",
      file: "/dev/projects/sf-flex-encore-vuejs/vendor\symfony\http-kernel\Kernel.php",
      line: 190,
      args: [
        [
          "object",
          "Symfony\Component\HttpFoundation\Request"
        ],
        [
          "integer",
          1
        ],
        [
          "boolean",
          true
        ]
      ]
    },
    {
      namespace: "Symfony\Component\HttpKernel",
      short_class: "Kernel",
      class: "Symfony\Component\HttpKernel\Kernel",
      type: "->",
      function: "handle",
      file: "/dev/projects/sf-flex-encore-vuejs/public/index.php",
      line: 25,
      args: [
        [
          "object",
          "Symfony\Component\HttpFoundation\Request"
        ]
      ]
    }
  ]
}

And when i implements what is said on the previous message i return to my 500 .

Here is a part of the security.yaml:

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        vuejs:
            pattern: ^/(demo/(vuejs|form|login/json(|/isloggedin|/logout))|api)
            anonymous: ~
            json_login:
                check_path: /demo/login/json
                # this doesn't work, see in the security.yaml:12 for more explanation
                #check_path: demo_login_json_check
                failure_handler: App\Security\AccessDeniedHandler
            logout:
                path:   demo_login_json_logout
                target: index
                invalidate_session: true

What's wrong ? coz the handler is never used when i run throught Xdebug
The project is available here : https://github.com/Rebolon/php-sf-flex-webpack-encore-vuejs/tree/fix/31-auth-500-instead-of-403
The route to test and reproduce is /demo/login/json/issue/sf-25806

@stof
Copy link
Member

stof commented Jan 16, 2018

Well, the message says it received a App\Security\AccessDeniedHandler instance in an argument expecting a Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface (see the error message at the beginning of the JSON response, before the stack trace).
Your own failure handler is buggy. It does not implement the AuthenticationFailureHandlerInterface and so it is not a failure handler.

@Rebolon
Copy link
Author

Rebolon commented Jan 16, 2018

@stof, yes indeed i've seen this error, but my AccessDeniedHandler implemented the AccessDeniedHandlerInterface because it's in the documentation here : https://symfony.com/doc/current/security/access_denied_handler.html

But in fact, when i've face that error, i've changed my AccessDeniedHandler to implement the AuthenticationFailureHandlerInterface (sorry i missed to afdd that informations) and this time, Symfony never walk throught my handler and i get back at the initial issue.

Here is my Handler:

<?php

namespace App\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;

// seen on this documentation https://symfony.com/doc/current/security/access_denied_handler.html
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Authorization\AccessDeniedHandlerInterface;

// but seems unrelated to json_login system :
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;

/**
 * Class AccessDeniedHandler
 *
 * For Security Component, you need to implement your own AccessDeniedHandler
 *
 * @package App\Api\Security\Security
 */
// When i just implement AccessDeniedHandlerInterface as said on the doc, then i got a 500 :
// Type error: Argument 1 passed to Symfony\Component\Security\Http\Authentication\CustomAuthenticationFailureHandler::__construct() must implement interface Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface, instance of App\Security\AccessDeniedHandler given, called in C:\dev\projects\fiducial\sf-flex-encore-vuejs\var\cache\dev\ContainerI18QW6b\getSecurity_Authentication_Listener_Json_VuejsService.php on line 8
//class AccessDeniedHandler implements AccessDeniedHandlerInterface
class AccessDeniedHandler implements AuthenticationFailureHandlerInterface, AccessDeniedHandlerInterface
{
    public function handle(Request $request, AccessDeniedException $accessDeniedException)
    {
        return new JsonResponse($accessDeniedException->getMessage(), 403);
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        return new JsonResponse($exception->getMessage(), 403);
    }
}

So i still have the probem

@stof
Copy link
Member

stof commented Jan 16, 2018

@Rebolon the doc also says to configure it under access_denied_handler, not under failure_handler. Configuring an AccessDeniedHandler inside failure_handler will never work (and trigger this invalid argument type error)

@Rebolon
Copy link
Author

Rebolon commented Jan 16, 2018

@stof not sure that the documentation is up to date and compatible with json_login coz it returns this:

Unrecognized option "access_denied_handler" under "security.firewalls.vuejs.json_login"

Whereas with the failure_handler (defined in symfony/security-bundle/DependencyInjection/Security/Factory/JsonLoginFactory.php L90) there is no Exception thrown by the framework

And if i move it under firewalls.vuejs instead of firewalls.vuejs.json_login then it does nothing and i still get my 500.

I don't know where to look for, thanks for help

@chalasr
Copy link
Member

chalasr commented Jan 17, 2018

access_denied_handler is a per firewall node, not per listener as opposed to failure_handler for the ones that support it. You're looking for json_login.failure_handler which must implement AuthenticationFailureHandlerInterface.

@chalasr
Copy link
Member

chalasr commented Jan 17, 2018

Documentation may be lacking (see symfony/symfony-docs#4258)

@Rebolon
Copy link
Author

Rebolon commented Jan 17, 2018

@chalasr thx, now i have identified that in fact my route had 'html' as default format. So it requires to set manually in the action annotation or generally in the routing.yaml

/**
 * This class is just here to reproduce the behavior described in this issue:
 * https://github.com/symfony/symfony/issues/25806
 */
class _FIX_ISSUE_SF_25806_Controller extends Controller
{
    /**
     * @Security("is_granted('IS_AUTHENTICATED_FULLY')")
     * @Route(
     *     "/demo/login/json/issue/sf-25806",
     *     defaults={"_format": "json"},
     *     )
     * @Method({"GET"})
     */
    public function reproductionForIssueSF28506()
    {
        return new JsonResponse("data");
    }
}

Now, when i try to a access the uri without be authentified i receive json content instead of html content, but the result is still a 500...

I understand what you said about the difference between access_denied_handler and failure_handler. But i don't understand why they are not used in my case.

I modified the security.yaml to get a simple one (in_memory user... and both error handlers):

security:
    encoders:
        # @todo should use password encoding, more info here: https://symfony.com/doc/current/security.html#c-encoding-the-user-s-password
        Symfony\Component\Security\Core\User\User: plaintext
    # https://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
    providers:
        in_memory:
            memory:
                users:
                    test:
                        password:           test
                        roles:              ROLE_USER
                    admin:
                        password:           admin
                        roles:              [ROLE_USER, ROLE_ADMIN]

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        vuejs:
            pattern: ^/(demo/(vuejs|form|login/json(|/isloggedin|/logout||/issue/.*))|api)
            anonymous: ~
            json_login:
                check_path: /demo/login/json
                # this doesn't work, see in the security.yaml:12 for more explanation
                #check_path: demo_login_json_check
                failure_handler: App\Security\AccessDeniedHandler
            access_denied_handler: App\Security\AccessDeniedHandler
            logout:
                path:   demo_login_json_logout
                target: index
                invalidate_session: true

With Xdebug, i can see that the this listener is catching the call : Symfony\Component\Security\Http\Firewall\UsernamePasswordJsonAuthenticationListener
It seems that this is the listener that will catch the request to perform the auth checks based on the check_path of my security context.
Because the uri is /demo/login/json/issue/sf-25806.json, it doesn't perform the check and let it go.

But then, it is the Sensio\Bundle\FrameworkExtraBundle\EventListener\SecurityListener that handle the request (i think it's because of the annotation is_granted of the managed route) and it loops over configurations inside the method onKernelControllerArguments.
Here is the value of the configuration (Xdebug capture):

[
   expression = "is_granted('IS_AUTHENTICATED_FULLY')"
   statusCode = null
   message = "Access denied."
]

Because the config, status is null so it retuen the AccessDeniedException instead of the HttpException

But at no moment my Handler is catching something with handle (failure_handler) or onAuthenticationFailure (access_denied_handler)

I'm sure that i'm missing something... I'v put breakpoints on Listeners that implements AuthenticationFailureHandlerInterface

Rebolon pushed a commit to Rebolon/php-sf-flex-webpack-encore-vuejs that referenced this issue Jan 17, 2018
it still fail coz my handlers are not managed by symfony
@chalasr
Copy link
Member

chalasr commented Jan 17, 2018

@Rebolon My guess is that removing the @Security annotation would make your failure handler reached. There are a number of incompatible/conflicting features between Symfony and SensioFrameworkExtraBundle... If I'm right, this should probably be reported on SensioFrameworkExtraBundle

@Rebolon
Copy link
Author

Rebolon commented Jan 17, 2018

@chalasr so you mean i should remove this annotation and do it programatically ? i'll give it a try and give you a feedback

@chalasr
Copy link
Member

chalasr commented Jan 17, 2018

yea, just to confirm the issues comes from there. Thanks

@Rebolon
Copy link
Author

Rebolon commented Jan 17, 2018

Here is the action:

    /**
     * @Route(
     *     "/demo/login/json/issue/sf-25806",
     *     defaults={"_format": "json"},
     *     )
     * @Method({"GET"})
     */
    public function reproductionForIssueSF28506()
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY', null, 'Unable to access this page!');

        return new JsonResponse("data");
    }

And my handlers are still not used (and i get the same exception as before).

Should i set my AccessDeniedHandler in my services.yaml ? i don't think so coz the security.yaml should declare it as listeners thanks to configurations access_denied_handler and failure_handler

@Rebolon
Copy link
Author

Rebolon commented Jan 17, 2018

Hey, maybe i've found why my handler (based on configuration failure_handler) is not managed:

Symfony\Component\Security\Http\Authentication\CustomAuthenticationFailureHandler::_construct L31 it checks if it has a setOptions methods

public function __construct(AuthenticationFailureHandlerInterface $handler, array $options)
    {
        $this->handler = $handler;
        if (method_exists($handler, 'setOptions')) {
            $this->handler->setOptions($options);
        }
    }

I'll confirm this (but why a programatic checks, instead of a hard typing based on Interface ? AuthenticationFailureHandlerInterface should not deinfe the setOptions ?)

@Rebolon
Copy link
Author

Rebolon commented Jan 17, 2018

Argh
Now the handler is added to the CustomAuthenticationFailureHandler, but it's still not used.
I'm like Sherlock Holmes looking for a solution...

@Rebolon
Copy link
Author

Rebolon commented Jan 18, 2018

Ok after more investigation i understand that the json_login.failure_handler is called when the check_path route is called and that the authentification failed (wrong user or password). And i can say that the failure_handler is working as expected.

So now i can focus on the access_denied_handler that is never called when i have an AccessDeniedException.

@Rebolon
Copy link
Author

Rebolon commented Jan 18, 2018

In symfony/security/Http/Firewall/ExceptionListener::handleAcessDeniedException::L120 there is a check on !$this->authenticationTrustResolver->isFullFledged($token)
This check will generate an InsufficientAuthentificationException or will allow to continue the process and give the hand to the accessDeniedHandler (which in my case is my App/Security/AccessDeniedHandler).

When i look at the isFullFledged method i can see that it will check the token. This token is a Symfony\Component\Security\Core\Authentification\Token\AnonymousToken so it's anonymous, but it's not a rememberMe token so the test will prevent to continue to the accessDeniedException.

If someone can give me more information about how to configure the Security Component to allow the access_denied_handler to run, that would be cool.
Also more information about Anonymous & RememberMe is welcome.

@chalasr
Copy link
Member

chalasr commented Jan 19, 2018

Looking at the code, the access_denied_handler being not reached in case of anonymous/remembered user seems expected, I don't have enough background on this part to tell if that should be changed. ping @stof @xabbuh

@xabbuh
Copy link
Member

xabbuh commented Jan 26, 2018

I am afraid I am of not much help here.

@Rebolon
Copy link
Author

Rebolon commented Feb 26, 2018

Using a Guard authentication solve my problem (but i still don't find if it's a problem on my side or on symfony side).
So i just follow this guide: https://symfony.com/doc/current/security/guard_authentication.html

But if this is the 'standard way' of using json_login (or another way) it should be specified in the documentation. For instance a json_login system in security component will always throw a 500 InsufficientAuthenticationException (i've just tried again on a new clean project with SF 4.0.4 and it's still the same behavior). If i'm wrong, tell me why :-)

@maps82
Copy link

maps82 commented Jun 8, 2018

We have the same problem with json_login (double exception resulting in a 500 instead of 401)

I don't understand why in Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginFactory there is no createEntryPoint method defined. So, as explained in #20233 (comment) there is no authenticationEntryPoint and the InsufficientAuthenticationException is thrown.

Maybe @dunglas (being the author of JsonLoginFactory) can help here?

@LPodolski
Copy link

LPodolski commented Jul 25, 2018

@maps82 @dunglas @stof

actually this problem is dated back to 2013

#8467 (comment)

to fix: InsufficientAuthenticationException / Full authentication is required to access this resource.

you need to create class:

<?php

declare(strict_types=1);

/**
 * This is required because otherwise symfony would throw HTTP 500 response,
 * when anonymous user try to access user protected route.
 * For some reason in @see JsonLoginFactory::createListener
 * entiry point is not defined likein @see FormLoginFactory::createEntryPoint
 * and it defaults to null
 * When it default to null @see InsufficientAuthenticationException
 * is being created, and in case of null entry point thrown here @see ExceptionListener::startAuthentication
 *
 * if (null === $this->authenticationEntryPoint) {
 *     throw $authException; // instance of: @see InsufficientAuthenticationException
 * }
 *
 * there are many issue ticket for this, dating back to 2013 so maybe some day it would be fixed:
 * @link https://github.com/symfony/symfony/issues/8467
 * @link https://github.com/symfony/symfony/issues/25806
 * @link https://github.com/symfony/symfony/issues/20233
 * @link https://github.com/Rebolon/php-sf-flex-webpack-encore-vuejs/issues/31
 */
class AuthenticationEntryPoint implements AuthenticationEntryPointInterface
{
    public function start(Request $request, AuthenticationException $authException = null): Response
    {
        return new JsonResponse([], Response::HTTP_UNAUTHORIZED);
    }
}

and security.yaml:

    firewalls:
        main:
            pattern: ^/
            entry_point: App\Security\ApiFrontAuthenticationEntryPoint

so that entrypoint in JsonLoginFactory would not be null, and therefore InsufficientAuthenticationException would not be thrown

of course there is no info about that:
http://symfony.com/doc/current/reference/configuration/security.html

or here:

https://symfony.com/doc/current/security/json_login_setup.html

not to mention that this kind of error should not be 500 inernal server error, just HTTP 401 unauthorised that indicates, reasonably, that user do is now anonymous, and therefore requires authorization to gain access to route where exception happened

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants