Liogate
Liogate

Reputation: 165

API Rest "The CSRF token is invalid. Please try to resubmit the form."

I'm looking to combine FOS Rest Bundle AND FOS User Bundle to my API application to register new users. The problem is:

How can I resolve those issues?

My POST Body

{
    "firstname": "xxx",
    "lastname": "xxx",
    "email":"[email protected]",
    "username":"xxx",
    "plainPassword":{
        "first":"xxx",
        "second":"xxx"
    }
}

Response:

{
    "errors": [
        "The CSRF token is invalid. Please try to resubmit the form."
    ],
    "children": {
        "email": {},
        "username": {},
        "plainPassword": {
            "children": {
                "first": {},
                "second": {}
            }
        },
        "firstname": {},
        "lastname": {}
    }
}

UserType Form

class UserType extends AbstractType
    {
        /**
         * @inheritDoc
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('firstname')
                ->add('lastname');
        }

        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'crsf_protection' => false,
                'csrf_token_id' => null,
                'data_class' => 'TM\UserBundle\Document\User'
            ]);
        }

        public function getParent()
        {
            return 'FOS\UserBundle\Form\Type\RegistrationFormType';

            // Or for Symfony < 2.8
            // return 'fos_user_registration';
        }
    }

The Controller

class UserController extends FOSRestController
{
    /**
     * @Rest\Post("/register")
     * @param Request $request
     * @return null|Response
     */
    public function postUserAction(Request $request)
    {
        /** @var $formFactory FormFactory */
        $formFactory = $this->get('form.factory');
        /** @var $userManager UserManagerInterface */
        $userManager = $this->get('fos_user.user_manager');
        /** @var $dispatcher EventDispatcherInterface */
        $dispatcher = $this->get('event_dispatcher');

        $user = $userManager->createUser();
        $user->setEnabled(true);

        $event = new GetResponseUserEvent($user, $request);
        $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event);

        if (null !== $event->getResponse()) {
            return $event->getResponse();
        }

        $form = $formFactory->create(UserType::class, $user);

        $form->submit($request->request->all());

        if ($form->isValid()) {
            $event = new FormEvent($form, $request);
            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event);

            $userManager->updateUser($user);

            if (null === $response = $event->getResponse()) {
                $url = $this->generateUrl('fos_user_registration_confirmed');
                $response = new RedirectResponse($url);
            }

            $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response));

            $view = $this->view(array('token' => $this->get("lexik_jwt_authentication.jwt_manager")->create($user)), Response::HTTP_CREATED);

            return $this->handleView($view);
        }

        $view = $this->view($form, Response::HTTP_BAD_REQUEST);
        return $this->handleView($view);
    }
}

Upvotes: 2

Views: 2012

Answers (1)

Jake Litwicki
Jake Litwicki

Reputation: 232

For an API you'll likely need to disable CSRF across the board, particularly if your API is processing data through forms directly (which I would recommend you do regardless).

You can find a clever solution for this here: https://stackoverflow.com/a/9888593/4620798

In your particular case, I think you may need to remove the csrf_token_id as it may be submitting a null value despite you telling the form to disable it anyway?

Separately, you'll probably end up running into PREFLIGHT issues if you're using Angular2 or any other "modern" frontend framework as the consumer. If/when you do there are solutions to that also :)

Upvotes: 1

Related Questions