Failing to get the current user Symfony

here is my set up :

Back : Symfony 6.1
Front : React

To get logged in, I use the JWT token of lexik bundle, which works grea. When logging in, I get my token and set it in a cookie, I get my current user in front.

But ine the back part, when I try to get the current user, it always returns null. Trying to do a Patch method returns an internal server error, saying basically that the current user is not found, which is strange as I am logged in on my post endpoint.

Here is my PATCH method, that is supposed to modify user’s informations :

#[Route('/api/users', name: 'api_modify', methods: "PATCH")]
public function updateUser(User $user = null, Request $request): Response
{
    $data = $request->getContent();
    $user = $this->getUser();

    try {
        $updatedUser = $this->serializer->deserialize($data, User::class, "json");
    } catch (NotNormalizableValueException $e) {
        return new JsonResponse("Erreur de type pour le champ '". $e->getPath() . "': " . $e->getCurrentType() . " au lieu de : " . implode('|', $e->getExpectedTypes()), Response::HTTP_UNPROCESSABLE_ENTITY);
    }
    $user
        ->setPassword($this->hasher->hashPassword($updatedUser, $updatedUser->getPassword()))
        ->setFirstname($updatedUser->getFirstName())
        ->setLastname($updatedUser->getLastName())
        ->setEmail($updatedUser->getEmail())
    ;

    $errors = $this->validator->validate($user);

    if (count($errors) > 0) {
        $myJsonError = new JsonError(Response::HTTP_UNPROCESSABLE_ENTITY, "Des erreurs de validation ont été trouvées");
        $myJsonError->setValidationErrors($errors);
        return $this->json($myJsonError, $myJsonError->getError());
    }

    $this->manager->flush();

    return $this->json(
        $user, Response::HTTP_OK,
        [],
        ['groups' => ['show_user']]
    );
}

And here is my front api call, made in my component :

export const Changeinfo = () => {

  const { register, handleSubmit, setValue, formState: { errors } } = useForm();
  const dispatch = useDispatch();
  const navigate = useNavigate();

  const changeinfoOnSubmit = async (data) => {
    try {
      let token = localStorage.getItem('token');
      const response = await axiosInstance.patch("https://stackoverflow.com/users", data, {
        headers: {
          'Authorization': `Bearer ${token}`
      }
      });
      dispatch(changeinfo(response.data));
    } catch (error) {
      console.error('Erreur lors du login', error);
    }
  };

  function getUser() {
    return JSON.parse(localStorage.getItem('user'));
  }

    const user = getUser();

    useEffect(() => {
      if (user && user.email) {
        setValue('email', user.email);
      }
      if (user && user.lastname) {
        setValue('lastname', user.lastname);
      }
      if (user && user.firstname) {
        setValue('firstname', user.firstname);
      }
    }, [user, setValue]);

  return (
    <div className={styles.Changeinfo}>
      <Navigation />
      <div className={styles.Changeinfo__cabinet}>
        <img src={image} alt="" />
        <h1>Mon espace membre</h1>
      </div>
      <form onSubmit={handleSubmit(changeinfoOnSubmit)}>
          <div>
            <input
              type="text"
              name="email"
              placeholder="Email"
              {...register('email', { required: true })}
            />
            {errors.username && <p>Le nom d'utilisateur est requis</p>}
          </div>
          <div>
            <input
              type="password"
              name="password"
              placeholder="Mot de passe"
              {...register('password', { required: true })}
            />
            {errors.password && <p>Le mot de passe est requis.</p>}
          </div>
          <div>
            <input
              type="text"
              name="lastname"
              placeholder="Nom de famile"
              {...register('lastname', { required: true })}
            />
            {errors.lastname && <p>Le nom de famille est requis</p>}
          </div>
          <div>
            <input
              type="text"
              name="firstname"
              placeholder="Prénom"
              {...register('firstname', { required: true })}
            />
            {errors.firstname && <p>Le prénom est requis</p>}
          </div>
          <button>Enter</button>
        </form>
    </div>
  )
}

I send back the token with the right informations,but here is the message I get :

PATCH http://localhost:8739/api/users 500 (Internal Server Error)
Changeinfo.jsx:30 Erreur lors du login AxiosError {message: ‘Request failed with status code 500’, name: ‘AxiosError’, code: ‘ERR_BAD_RESPONSE’, config: {…}, request: XMLHttpRequest, …}

When trying from Postman, the error points that $this->getUser() is the source of the problem.

How is it possible that I can logging easily, but the user back side remains null ?

My security.yml :

firewalls:

    login:
        pattern: ^/api/login
        stateless: true
        json_login:
            check_path: /api/login_check
            success_handler: lexik_jwt_authentication.handler.authentication_success
            failure_handler: lexik_jwt_authentication.handler.authentication_failure

    api:
        pattern: ^/api
        stateless: true
        jwt: ~
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        lazy: true
        provider: app_user_provider
        custom_authenticator: App\Security\LoginFormAuthenticator
        logout:
            path: app_logout
            # where to redirect after logout
            # target: app_any_route

        # activate different ways to authenticate
        # https://symfony.com/doc/current/security.html#the-firewall

        # https://symfony.com/doc/current/security/impersonating_user.html
        # switch_user: true

# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
    # - { path: ^/admin, roles: ROLE_ADMIN }
    # - { path: ^/profile, roles: ROLE_USER }
    - { path: ^/admin, roles: ROLE_ADMIN }
    - { path: ^/api/login, roles: PUBLIC_ACCESS }
    - { path: ^/api/signup, roles: PUBLIC_ACCESS }
    #- { path: ^/api/users,  roles: IS_AUTHENTICATED_FULLY }

My lexik_jwt_authentication.yaml :

lexik_jwt_authentication:
    secret_key: '%env(resolve:JWT_SECRET_KEY)%'
    public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
    pass_phrase: '%env(JWT_PASSPHRASE)%'
    token_ttl: 3600 # in seconds, default is 3600

  • Well, in my security.yaml I have some access control configured, and firewall but that’s all. I am using LexikJWTAuthenticationBundle, version 2.19.1.

    – 

  • I put it in answer, was too long to post here

    – 

  • Can you uncomment your access control line concerning api/users - { path: ^/api/users, roles: IS_AUTHENTICATED_FULLY } and try again ?

    – 

  • I get a 401 because according to symfony, i’m not fully authenticated. In my controller, $this->getUser() returns null. That is the real problem I guess { “code”: 401, “message”: “JWT Token not found” }

    – 




  • Did you get a JWT Token not found error ? have you checked if your request contains your token ?

    – 

Leave a Comment