ren Posted January 6, 2019 Share Posted January 6, 2019 (edited) There is already some information on how to do this but it's a bit scattered, so here's a quick tutorial... This is how $session->CSRF->hasValidToken() handles AJAX requests, by getting the token name and value from request headers: if($this->config->ajax && isset($_SERVER["HTTP_X_$tokenName"]) && $_SERVER["HTTP_X_$tokenName"] === $tokenValue) { $valid = true; } else if($this->input->post($tokenName) === $tokenValue) { $valid = true; } So all we need to do is to pass the name and value to our JavaScript and set the right headers with our AJAX request. We could instead of setting headers put the name and value pair into the body of a POST request, as the second conditional doesn't care if the POST request is received via AJAX or not. But this limits the request to POST and the body data type to either multipart/form-data or application/x-www-form-urlencoded (because that's all that PHP's $_POST superglobal will handle). Admittedly this might be 99% of use cases, but for example if a GET request invokes significant processing then CSRF protection could be used to prevent a DOS attack on the endpoint. So, for the sake of a bit more flexibility, and to be more in keeping with what PW expects, we'll use request headers. I find it neater to write the token name and value into HTML and retrieve that using JavaScript DOM functions, instead of writing JavaScript with PHP ?. So somewhere, maybe in init.inc.php, get the token name and value: $csrfTokenName = $session->CSRF->getTokenName(); $csrfTokenValue = $session->CSRF->getTokenValue(); Then in a global footer template: <div class="js-csrf-token" style="display:none;" data-csrf-token-name="<?php echo $csrfTokenName; ?>" data-csrf-token-value="<?php echo $csrfTokenValue; ?>"></div> Now to retrieve the token in JavaScript: function getCsrfToken() { const csrfTokenNode = document.getElementsByClassName('js-csrf-token')[0]; return { name: csrfTokenNode.getAttribute('data-csrf-token-name'), value: csrfTokenNode.getAttribute('data-csrf-token-value'), } } Then in any AJAX request: const csrfToken = getCsrfToken(); let xhr = new XMLHttpRequest(); // ... // open the request and do some configuration // ... xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // tell the server and PW that it's an AJAX request xhr.setRequestHeader('X-' + csrfToken.name, csrfToken.value); // create a header with the token // ... // send the request // ... And that's all, in the endpoint just do... if ($session->CSRF->hasValidToken()) { // works for AJAX! } This has used the default CSRF token created for every session, but to create and use a different token just specify an id: $csrfTokenName = $session->CSRF->getTokenName('myAjaxToken'); // this creates a token if one with the given id doesn't exist $csrfTokenValue = $session->CSRF->getTokenValue('myAjaxToken'); and... if ($session->CSRF->hasValidToken('myAjaxToken') { // ... } Edited January 7, 2019 by ren 9 5 Link to comment Share on other sites More sharing options...
Zeka Posted January 6, 2019 Share Posted January 6, 2019 @ren Great tutorial, thanks. 2 Link to comment Share on other sites More sharing options...
bernhard Posted November 13, 2020 Share Posted November 13, 2020 Thx, that helped me a lot today ? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now