Edwardo Afundoh
Edwardo Afundoh

Reputation: 626

How to add csrf token to ajax request

I have issues adding csrf to ajax request. I'm using thymeleaf on client side with spring-boot/spring security. Spring security wouldn't allow the request because csrf-token is missing. Here is my code for ajax

function bits(){
    var xhttp = new XMLHttpRequest();
    var selected = document.getElementById("product").value;
    xhttp.onreadystatechange = function(){
      if(xhttp.readyState==4 && xhttp.status==200){
        var result= JSON.parse(xhttp.responseText)
        var length = result.length;
        for(i=0; i<length; i++){

           console.log(result[k].spid);
        }
    }

};

 xhttp.open("POST", "http://localhost:8080/bids?q="+selected,  true);
 xhttp.send();

}

Help will be appreciated

Upvotes: 16

Views: 18759

Answers (6)

Marios
Marios

Reputation: 1957

In spring documentation, it is also suggested that you do not use csrf token in GET requests for security reasons

"The ability to scope which requests receive the token helps guard against leaking the CSRF token to a third party."

You can therefore filter to pass token only for POST requests with following manner:

$(function() {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function(e, xhr, options) {
        if (options.type == "POST") {
            xhr.setRequestHeader(header, token);
        }
    });
});

The meta tags in <head> element would be the same as in previous answers:

<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>

Upvotes: 4

Edwardo Afundoh
Edwardo Afundoh

Reputation: 626

I modified @Prakash Hari Sharma's solution and had the following code that worked for me. Note, th: prefix if using Thymeleaf.

--Header section

<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>

Ajax script function

...
...
var token = $("meta[name='_csrf']").attr("content"); 
var header = $("meta[name='_csrf_header']").attr("content");
...
...
xhttp.open("POST", "http://localhost:8080/bids?q="+selected,  true);
xhttp.setRequestHeader(header, token);
xhttp.send();

Hope this helps someone too.

Upvotes: 20

hzitoun
hzitoun

Reputation: 5832

You can set the Spring Security's CSRF Token into a Javascript variable called MyApp.csrfToken.

In your JSP, add the flowing script to call the init function once your document is ready:

<script type="text/javascript">
    document.onreadystatechange = function () {
       var state = document.readyState;
       if (state == 'complete') {
         fnInit("${_csrf.parameterName}", "${_csrf.token}"); 
       }
    }​;
</script>

In your JS file, define the fnInit function

var MyApp = MyApp || {};
function fnInit(csrfParam, csrfToken) {
  MyApp.csrfToken = {
      param : csrfParam,
      value : csrfToken
  }
}

Now you have the token ready to use in any ajax call

...
...
xhttp.open("POST", "http://localhost:8080/bids?q="+selected + "&"+ MyApp.csrfToken.param+"="+ MyApp.csrfToken.value,  true);
xhttp.send();

PS: No need for jQuery, it is pure JavaScript.

Upvotes: 0

Tomasz Mularczyk
Tomasz Mularczyk

Reputation: 36179

As a complementary to @EdwardoS answer, after you add meta tags to the <head> element:

Thymeleaf:

<meta th:name="_csrf" th:content="${_csrf.token}"/>
<meta th:name="_csrf_header" th:content="${_csrf.headerName}"/>

JSP:

<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>

...you can then do what is suggested in Spring documentation and have all your future ajax to include csrf:

$(function () {
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $(document).ajaxSend(function (e, xhr, options) {
        xhr.setRequestHeader(header, token);
    });
});

Upvotes: 13

Prakash Hari Sharma
Prakash Hari Sharma

Reputation: 1424

Store CSRF Token in your jsp meta tags

<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>

and add values of csrf token in ajax request

var elementToken = document.querySelector('meta[property="_csrf"]');
var token = elementToken && elementToken.getAttribute("content");
var elementHeader = document.querySelector('meta[property="_csrf_header"]');
var header = elementHeader && elementHeader.getAttribute("content");
xhttp.open("POST", "http://localhost:8080/bids?q="+selected,  true);
xmlhttp.setRequestHeader(header, token);
xhttp.send();

Upvotes: 3

Cristian
Cristian

Reputation: 101

below you can find my code to use ajax with csrf. I use Spring Security too.

    // In your JSP meta tags
    <meta name="_csrf" content="${_csrf.token}"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" content="${_csrf.headerName}"/>

    // In your javascript
    // CSRF Variables
    var _tc = $("meta[name='_csrf']").attr("content");
    var _hc = $("meta[name='_csrf_header']").attr("content");


    // Header
    var headersStomp = {};
    headersStomp[_hc] = _tc;

    $(document).ajaxSend(function(e, xhr, options) {
        xhr.setRequestHeader(_hc, _tc);
    });

Upvotes: 2

Related Questions