I am writing Rest Api with Spring and use jQuery for the app on the front which uses this api. Session is stored in a cookie so I need CSRF protection with tokens. Token is send in a request/response header and stored in meta tags on the page. This is not full SPA, hence at the authentication and registration i send separate html pages: index.html(for authenticated users), login.html(login page), register.html(registration page). Here is the problem, i don't know how to retrieve csrf token at registration and login because first and only request is always POST but somehow i need to set csrf token on the page first. Static pages i retrieve is just by calling static resources with: window.location = '/register.html'; for example. I tried to set get request for "/token" endpoint which returns ResponseEntity with status only and fetch token from header, but then error shows in javascript that jqXHR.getResponseHeader('X-CSRF-TOKEN') is not a function.... weird. How can write method with jquery which will retrieve token from header in this case?
For example here my register.js file and how i handle fetching and attaching tokens.
In login page i have button whch redirects on registration page:
$('#registerBtn').on('click', function () {
window.location = '/register.html';
});
--------------------------------
And registration page is:
$(document).ready(function () {
setCsrfToken();
$('#submit').on('click', function () {
return $.ajax({
url: '/registration',
type: 'POST',
beforeSend: function (request) {
setHeaderWithCsrfToken(request);
},
data: $('#registrationForm').serialize(),
timeout: 3000
}).then(function (data, textStatus, jqXHR) {
console.log(jqXHR.status);
}, function (jqXHR) {
if (jqXHR === 422) {
// $('#registrationForm').append(jqXHR);
alert(jqXHR.status);
} else {
alert(jqXHR.status);
}
});
});
});
// simple get method to retrieve response header with token
function setCsrfToken() { // TODO: how to make it reusable?
return $.ajax({
url: '/token',
type: 'GET',
timeout: 3000
}).always(function (jqXHR) {
getCsrfToken(jqXHR);
});
}
function getCsrfToken(jqXHR) {
$('meta[name="X-CSRF-TOKEN"]').attr('content',
jqXHR.getResponseHeader('X-CSRF-TOKEN'));
$('meta[name="X-CSRF-HEADER"]').attr('content',
jqXHR.getResponseHeader('X-CSRF-HEADER'));
}
function setHeaderWithCsrfToken(request) {
var token = $('meta[name="X-CSRF-TOKEN"]').attr('content');
var header = $('meta[name="X-CSRF-HEADER"]').attr('content');
request.setRequestHeader(header, token);
}
I think you use the wrong argument in the AJAX callback function. Try this:
$.ajax({
url: '/token',
type: 'GET',
timeout: 3000
}).done(function (data, textStatus, jqXHR) {
getCsrfToken(jqXHR);
});