How to handle CSRF token using XMLHTTPRequest? - javascript

I am using an API which is protected by CSRF. So I need to do a get call to fetch CSRF token and then pass the same token to do POST call.
Below is the way I tried, but i always get CSRF Token Validation failed as response for the POST call.
var tryout = new XMLHttpRequest();
tryout.open("GET", "/api/1.0/csrf");
tryout.withCredentials = true;
tryout.setRequestHeader("x-csrf-token", "fetch");
tryout.setRequestHeader("Accept", "application/json");
tryout.setRequestHeader("Content-Type", "application/json; charset=utf-8");
tryout.onreadystatechange = function () {
console.log(this);
var csrfToken = this.getResponseHeader('x-csrf-token');
if(tryout.readyState == 4){
console.log(csrfToken);
tryout.open('POST', '/api/1.0/create');
tryout.setRequestHeader('x-csrf-token', this.getResponseHeader('x-csrf-token'));
tryout.onreadystatechange = function () {
console.log("call 2");
console.log(this.responseText);
};
tryout.send();
}
};
tryout.send();
I am suspecting may be POST call is starting new session and so CSRF is not valid for that session.
Please guide me How to do two xhr calls in same session ?

I tried sync calls with XMLHTTPRequest using same xhr object for both calls ( fetching csrf token and next http post call passing csrf token in header and it worked. Below is the sample code.
var res = null;
var tryout = new XMLHttpRequest();
tryout.open("GET", "/odata/1.0/service.svc", false);
tryout.withCredentials = true;
tryout.setRequestHeader("x-csrf-token", "fetch");
tryout.setRequestHeader("Accept", "application/json");
tryout.setRequestHeader("Content-Type", "application/json; charset=utf-8");
tryout.send(null);
if(tryout.readyState === 4){
var csrfToken = tryout.getResponseHeader('x-csrf-token');
tryout.open('POST', '/odata/1.0/service.svc/Clients', false);
tryout.setRequestHeader('x-csrf-token', csrfToken);
tryout.setRequestHeader("Content-Type", "application/json; charset=utf-8");
tryout.setRequestHeader("Accept", "application/json");
tryout.send(JSON.stringify(obj));
if(tryout.readyState === 4){
res = JSON.parse(this.responseText);
}
}

"x-csrf-token", "fetch" is for the GET method to fetch the data. Then you will get the csrf token value. Just copy that and add that in your code may be it will work.

Related

HTTP Post Request not working throwing error "XMLHttpRequest" is not defined

I'm pretty new to javascript and am working on an integration system.
This is a small integration system, so I can't use Ajax or add any other normal web technologies, I just need to use Javascript to send a HTTP POST and get response only after success, so my first goal is to be able to send that POST message
I have written code but i am getting error
Exception in map activity: org.mozilla.javascript.EcmaError: ReferenceError: "XMLHttpRequest" is not defined.
function abc(){
var url = "https://na10.saourt.com/se/sendData";
var method = "POST";
var postData ="[{\"name\":\"anderson\",\"ContactEmail\":\"ad#gmail.com\"}]";
var async = true;
var request = new XMLHttpRequest();
request.onload = function () {
var status = request.status;
var data = request.responseText;
}
request.open(method, url, async);
request.setRequestHeader("Content-Type", "application/json");
request.setRequestHeader("Authorization", "OAuth 123");
request.setRequestHeader("securityToken", "123#abs");
request.send(postData);
}
Have you tried sending an empty/basic post request?

Tableau REST API: Using Javascript to get the Token

I am a complete beginner with REST API and I could not figure out how I am to proceed.
I installed Postman and was successfully able to get the Token, but I am not sure how to send the raw XML payload in javascript.
<tsRequest>
<credentials name ="XXX" password="YYY" >
<site contenturl = "" />
</credentials>
</tsRequest>
I have :
httpRequest.open('POST', 'http://MY-SERVER/api/2.4/auth/signin', false);
httpRequest.setRequestHeader("Content-type", "application/xml");
Not sure how to add the xml payload. I have access to a Tableau Server(MY-SERVER) and everything.
Any help would be greatly appreciated!
Thank you!
You are getting closer, you just need to use the send method to send your XML: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send
Just make sure that your XML is properly encoded in javascript when you're inputting it. So if you are using double quotes inside your XML, make sure you have single quotes to declare your string in javascript (e.g.) var data = '<credentials name="XXX" >';
Related: Send POST data using XMLHttpRequest
In addition to #AnilRedshift answer, here's the functioning code:
login_details=[];
function getToken() {
var url = "http://yourServerAddress/api/2.0/auth/signin";
var params = "<tsRequest><credentials name='Username' password='UserPassword' ><site contentUrl='' /></credentials></tsRequest>";
return zuo = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.withCredentials = true;
xhr.onload= function(){
if (this.status === 200) {
var parsed_xml = JSON.parse(JSON.stringify(x2js.xml_str2json(xhr.responseText)))
login_details.push(parsed_xml.tsResponse.credentials._token); login_details.push(parsed_xml.tsResponse.credentials.site._id);
resolve(login_details);
}
}
xhr.onerror=reject;
xhr.send();
})
}
function getWorkbooks(){
var url = "http://serveraddress//api/2.3/sites/"+login_details[1]+"/workbooks?pageSize=1000";
return zuo = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-Tableau-Auth",login_details[0]);
xhr.onload= function(){
if (this.status === 200) {
var workbooks = JSON.parse(JSON.stringify(x2js.xml_str2json(xhr.responseText)))
for (var f=0;f<workbooks.tsResponse.workbooks.workbook.length;f++){
if(workbooks.tsResponse.workbooks.workbook[f].project._name=="Default"){
workbooks_list.push(workbooks.tsResponse.workbooks.workbook[f]._id)
}
resolve();
}
}
}
xhr.onerror= function(){
console.log(xhr.responseText);
}
xhr.send();
})
}
Invoke the code with:
getToken()
.then(function(login_details){
console.log(login_details[0]+"/"+login_details[1]);
})
.then(function(){
getWorkbooks();
})
getToken() function gets the login token which has to be used in all subsequent calls.
getWorkbooks() fetches all dashboards in 'Default' project but this kind of request can be used for all GET type requests.
Please note that this approach uses hardcoded values for password and username which is generally not the best practice. It would be way better to use server side scripting or encrypting (better but still with flavs).
You can find whole step by step tutorial and running code here:
http://meowbi.com/2017/10/23/tableau-fields-definition-undocumented-api/

Is there a way to preserve cookies between two separate XMLHttpRequests?

As indicated in the code snippet below, I am trying to extract a token from the response obtained from the first call made on XMLHttpRequest. I then want to send the token in the second POST call ensuring that cookies are the same. But, I am not able to figure out a way to preserve the cookies yet. Could someone share what I am missing here?
//First XMLHttpRequest below
xhr = new XHR();
xhr.onreadystatechange = extractLoginToken;
xhr.open( "GET", url );
xhr.setRequestHeader('Set-Cookie', "abc");
xhr.withCredentials = true;
xhr.send();
function extractLoginToken() {
var params = "token=" + this.responseText.query.token;
var cookie = xhr.getResponseHeader('Set-Cookie');
//Second call
xhr = new XHR();
xhr.withCredentials = true;
xhr.open( 'POST', url_1 );
xhr.setRequestHeader('Set-Cookie', cookie);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send( params );
}

How to send csrf token in AJAX request (Without Jquery) in expressjs?

I am using the csurf module in expressjs. It works for all post requests as I use it the following way.
app.use(csrf());
res.locals.csrfToken = req.csrfToken();
This way its automatically available in all forms where I have the following.
<input type="hidden" name="_csrf" value="<%=csrfToken%>">
but how do I set the csrftoken on AJAX requests, I am not using jquery, below is the JS function to send AJAX request. I do have the csrf token available on the html as a hidden value that I have access via getElementByID.
note: I am able to send the request if I disable csrf.
function voteQuestion () {
var qid = document.getElementById("qid").value;
var csrf = document.getElementById("csrf").value;
var http = new XMLHttpRequest();
var url = "/q/ajaxcall";
var params = "qid="+ qid;
http.open("POST", url);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {
if(http.readyState == XMLHttpRequest.DONE && http.status == 200) {
var json = (http.responseText);
var obj = JSON.parse(json);
document.getElementById("vote-sp").innerHTML = (obj.upvotes);
}
};
http.send(params);
}
I have been trying to figure this out for almost a week now, and just decided to console.log req.session and found cookies contains "XSRF-TOKEN" value, so in the AJAX request header I set XSRF-TOKEN to csrf and now it works, I dont know why it works this way particularly for AJAX requests.
setRequestHeader("XSRF-TOKEN", csrf);
Set crsf token in your params as below..
var params = "qid="+ qid + "&crsf="+csrf;
OR
You can create a new object for sending data as below..
var data = {}; //crates new object
data.qid = qis; //adds qid to object
data.csrf = csrf; //adds qid to object
params = data; // to server

How to send JSON response from python server to the javascript using ajax call

elif self.path == "/recQuery":
r = requests.get('http://example.com') # This returns some json from a request to another server.
print r.json()
self.wfile.write(r.json())
.
var http = new XMLHttpRequest();
var url = SERVER + "/recQuery";
var params = JSON.stringify({
query: search_query
});
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send(params);
console.log(http.responseText);
How can i send data from python server to javascript using ajax call. The one i am using does not return anything in the console. Can you please tell me what i am doing wrong here. I need send the response of what i get from requests.get method to the ajax call. The json should be returned to the ajax call in response. Problem is with the self.wfile.write method, When i use this i dont get anything on javascript side.
var http = new XMLHttpRequest();
var url = SERVER + "/recQuery";
var params = JSON.stringify({
query: search_query
});
http.onreadystatechange = function() {
if (http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
};
http.open("POST", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send(params);
I was not fetching the response onreadystatechange. So this works for me. Thanks !

Categories

Resources