Home > front end >  $user null but not null on json login
$user null but not null on json login

Time:02-23

I have a very weird behavior on symfony 6 with json login. Json login is configured like in their example.

I added the most simple Cors-handling

class CorsSubscriber implements EventSubscriberInterface
{
    public function onKernelResponse(ResponseEvent $event)
    {
        $response = $event->getResponse();
        $response->headers->add([
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Headers' => 'Content-Type'
        ]);
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::RESPONSE => 'onKernelResponse',
        ];
    }
}

Login Controller

class LoginController extends AbstractController
{

    #[Route('/login', name: 'api_login')]
    public function login(#[CurrentUser] ?User $user): JsonResponse
    {
        if ($user === null) {
            $this->json([
                'message' => 'Not found',
            ], JsonResponse::HTTP_UNAUTHORIZED);
        }

        $token = "token"; // some token logik follows

        $response = new JsonResponse([
            'user' => $user->getUserIdentifier(),
            'token' => $token,
        ]);

        return $response;
    }
}

Again, basically straight out of their tutorial.

DB is also set up and a user was added beforehand. If I now want to login via a Rest App (I use Insomnia) everything works as expected. I get the user identifier (email) and token back.

But when I want to do the exact same thing via an Angular web app, I get the following message in the log: [critical] Uncaught Error: Call to a member function getUserIdentifier() on null

    let data = {username: "[email protected]", password: "test123"};
    this.http
      .post('http://localhost:8000/login', data)
      .subscribe({
        next: (value) => {
          console.log(value);
        },
      });

Funny thing since I check if $user is null... But the most funny thing is, if I change the $user->getUserIdentifier() call to just "$user" - it works and I get the whole User object returned (everything I defined in json_serializable)

Again, getUserIdentifier is from symfony itself

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUserIdentifier(): string
    {
        return (string) $this->email;
    }

What am I missing?

CodePudding user response:

In the documentation check_path: api_login is defined in the "security.yaml ".

In the ApiLoginController #[route('/api/login', name:'api_login')]

I wanted to change this to the path "/login".

Thereby I defined check_path: login in security.yaml

and in the controller #[route('/login', name:'api_login')]

However, the name must also be "login", like #[route('/login', name:'login')]

CodePudding user response:

Found out what's wrong.

  1. No return
        if ($user === null) {
            $this->json([
                'message' => 'Not found',
            ], JsonResponse::HTTP_UNAUTHORIZED);
        }

I missed the return before $this->json, allowing the call to proceed even while $user was indeed null.

  1. Preflight Cors

I honestly don't have too much experience and knowledge about cors and wasn't really aware about the preflight calls being done. But that was the problem.

    public function onKernelRequest(RequestEvent $event)
    {
        if (!$event->isMainRequest()) {
            return;
        }
        $request = $event->getRequest();
        $method  = $request->getRealMethod();
        if ('OPTIONS' == $method) {
            $response = new Response();
            $event->setResponse($response);
        }
    }

    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::RESPONSE => ['onKernelResponse', 9999],
            KernelEvents::REQUEST => ['onKernelRequest', 9999]
        ];
    }

I extended the CorsSubscriber to check for Method OPTION if it is not the main request and just sending a 200 to pass the preflight. This helped me understand the logic behind it:

  • Related