9

I have CSRF enabled on my install. I have a bunch of frontend forms so CSRF is pretty important for me. However, when I use AJAX to post to a controller action I get the following error.

<div id="message" class="pane">
    <h2>Bad Request</h2>
    <p>The CSRF token could not be verified.</p>
</div>

Here is my AJAX that I am testing with.

$(function(){
    var data = { id: 100 };
    $.post("/actions/gistClient/exampleAjax", data, function(response) {
        console.log("success", response, data);
    });
});

Here is my controller action

public function actionExampleAjax()
{
    $this->requireAjaxRequest();
    // ... whatever your AJAX does...
    $response = array('response' => 'Round trip via AJAX!');
    $this->returnJson($response);
}

Is it possible to disable CSRF for certain routes? Alternatively, how would I pass CSRF through AJAX to the controller action?

2 Answers 2

22

Disabling the CSRF protection is probably a bad idea... it's in there for a reason. But you can easily add your CSRF data to an AJAX call, and it works very well!

The key is to make your CSRF token name & value available in your front-end JS. You can then pass that into your AJAX call as an additional value.

There are a few ways to push the CSRF data to the front-end, so this is simply one example:

{# Get CSRF token info in Twig #}
{% set csrfToken = {
    name: craft.app.config.general.csrfTokenName,
    value: craft.app.request.csrfToken,
} %}

{# Pass CSRF token through to JavaScript (via the page head) #}
{% js "window.csrfToken = #{csrfToken|json_encode|raw};" at head %}

Once you have the CSRF info on the front-end, simply add it to your AJAX data...

$(function(){
    // Whatever data is being passed via AJAX
    const data = { id: 100 };

    // Append CSRF Token
    data[window.csrfToken.name] = window.csrfToken.value;

    // Make the AJAX call
    $.post('actions/example-controller/example-action', data, function(response) {
        console.log('success', response, data);
    });
});

That's it! Your AJAX call should now submit properly.

2
  • If anyone wonders (like I did) how to do that when uploading files – here is the answer: stackoverflow.com/a/16762012/2342963 Commented Nov 3, 2016 at 7:20
  • 1
    There is a section in the documentation on Ajax that provides some additional methods for working with CSRF protection! Commented Feb 27 at 0:27
10

This is the syntax for Craft 3:

<script type="text/javascript">
    window.csrfTokenName = "{{ craft.app.config.general.csrfTokenName }}";
    window.csrfTokenValue = "{{ craft.app.request.csrfToken }}";
</script>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.