The csrf token is session based, because of the sulu caching mechanism it is needed to be load that token over a separate request (ajax).
Enable csrf protection for dynamic forms via:
sulu_form:
csrf_protection: true
We need to add a new Route
generates use the csrf token for the ajax based loading:
# config/routes/sulu_form.yaml
sulu_form.token:
path: /_form/token
defaults:
_controller: Sulu\Bundle\FormBundle\Controller\FormTokenController::tokenAction
_requestAnalyzer: false
A simple example for loading the csrf token over ajax looks like this:
# your-theme.html.twig
{%- block csrf_token_widget -%}
{{ block('hidden_widget') }}
{# this is just an example it should use data attributes or something similar to read formName and fieldId #}
<script>
var formName = '{{ form.parent.vars.name }}';
var fieldId = '{{ id }}';
</script>
{% endblock %}
fetch('/_form/token?form=' + formName + '&html=0', {
credentials: 'same-origin', // required for old safari versions
headers: {
'X-Requested-With': 'XMLHttpRequest',
},
}).then((response) => {
return response.text();
}).then((token) => {
document.getElementById(fieldId).value = token;
});
When using @sulu/web
/ sulu/web-twig
component library, loading the csrf token over ajax looks like this:
{# templates/form/your-theme.html.twig #}
{% extends '@SuluForm/themes/basic.html.twig' %}
{%- block csrf_token_widget -%}
{{ block('hidden_widget') }}
{% do prepare_component('csrf-token', { id: id, formName: form.parent.vars.name }) %}
{% endblock %}
// assets/website/js/componenes/csrf-token.js
export default class CsrfToken {
initialize(el, options) {
fetch('/_form/token?form=' + options.formName + '&html=0').then((response) => {
if (!response.ok) {
return Promise.reject(response);
}
return response.text();
}).then((data) => {
el.value = data;
});
}
}
// assets/website/js/main.js
import web from '@sulu/web';
import CsrfToken from './components/csrf-token';
web.registerComponent('csrf-token', CsrfToken);