Vue.js and Symfony Forms – DZone Web Dev
Symfony provides us the
symfony/form package which makes the handling of rendering and submitting forms easier than ever. Soon this will become even easier with the new “Form handler helper”, but that’s not the point here.
What annoyed me when I first started working with Vue.js was the fact that I pretty much like the need to say “goodbye” to the forms rendering directly in the Twig (which is very handy).
I’ve started searching for some “form generators” packages for Vue.js. There are a few, but so far I didn’t like any of them. In the worst case, I could just render the form in some kind of API method like
/get-form-view but this is so against the Vue.js workflow/concept.
So… I started to ask myself and think:
“How can I render forms in Vue.js and handle them in Symfony? While I can quit rendering the forms like Twig handles it — I definitely want to keep the Form validations/handling provided by Symfony.”
There are few problems that need to be solved here:
- Handling of CSRF token,
- Rebuilding the request “it’s structure must be the same of that provided upon Symfony standard form submission.”
By default, each Form created with
symfony/form packages have the CSRF Token validation turned on. Meaning further that each request provided to the form handler must contain the CSRF Token. There are few solutions here, I will go with the 2 that I found for my case.
The bad one (unless it’s just your private project) — disabling the CSR Token validation
Each form class (meaning that it extends from
SymfonyComponentFormAbstractType ) allows us to turn the CSRF validation off.
While this is ok for small private projects or internal ones, it’s one big no when it comes to a publicly accessible project.
Sending and Handling the CSRF Token With Vue.js Call — The Good Solution
1. First thing to do is… disabling the
csrf_protection like above.
2. Now we need
3. Now the check for token must be done in 2 places:
- as I wrote in other article (here), each request goes through
Authenticator— so the request must be validate inside of it as this is called before the
4. We also need a route which will deliver the CSRF token:
Now instead of adding
getCsrf over and over again in each Axios call, I wrote my own plugin to handle the post-call with CSRF token call alongside.
Simply the plugin does 2 things:
- Calls backend: “Hey — give me CSRF token for this UUID.”
- Then makes a second call: “Hey — I got this CSRF for UUID, please check it and let me through.”
Naturally, nobody says that the token must be fetched on the moment that ajax call is done, it can as well be fetched in the
beforeMount and then supplied in form, I just see no reason for that, as we must communicate backed for token anyway.
So.. does it actually work correctly if we would provide a fake CSRF token? Yes — I did a test with a hardcoded token in code and the request was rejected.
Not a Perfect Solution
While this is doesn’t sound perfect it works pretty much the way that Symfony handles the CSRF tokens:
- It uses the
- It generates a new token on each request.
Rebuilding the Request
Now once the CSRF token validation is working, here comes the easiest part actually. We simply need a logic that will “take the Axios request — json” and transform it into proper Request data used normally in Symfony.
And just use it like this:
My Thoughts to This Solution
The only main concern that I got here is that
getCsrf route should be hidden behind authentication and only the
login should be allowed to pass it without authentication, otherwise upon “fake form” and copied front logic anyone can easily fetch the CSRF token.
Another nice “in-case” protection would be just checking where does the request comes from — if outside of our domain then — block it, thus nobody will ever get the token.
Other than this, is just that it took a bit to understand how to generate the CSRF token, validate it, handle the request, and so on — so it’s time-consuming when doing it for the first time, but other than that it can be copied and reapplied.
And hey… the Symfony Form Validation is working as it should!
Credit: Source link