Sending 'Authorization' header in Ext JS Ajax Request, Chrome vs. Firefox - javascript

In code the request is sent as:
var ajaxOptions = {
url: 'someUrl',
method: 'POST',
success: function(response) {
...
},
failure: function(response) {
console.log(response);
}
};
var form = this.getView().getForm();
var submitAction = Ext.create('Ext.form.action.Submit', { form: form });
var formInfo = submitAction.buildForm();
ajaxOptions.form = formInfo.formEl;
if (form.hasUpload()) {
ajaxOptions.isUpload = true;
}
Ext.Ajax.request(ajaxOptions);
When a request is sent via Chrome, the 'Authorization' header presents:
Authorization:Basic YWRtaW46YWRtaW4=
When it is sent via Firefox, the header is not included.
Explicitely I don't set user/password. So it's not clear, why and how chrome sends such header. Are there any known issues?
The second, how to force firefox to send such header? Is it possible?
UPDATED
JavaScript does not now anything about login/password. The main question, how Chrome can use them, but other browsers cannot send such pair. So the question is how to force other browsers to send this cookie as Chrome does without appling headers manually via JavaScript.
On the server side, the Servlet API is used. in web.xml:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>someName</realm-name>
</login-config>
if it does matter

Per the docs, just add a headers property to your ajaxOptions:
ajaxOptions = {
//...
headers : {
'Authorization': 'Basic YWRtaW46YWRtaW4='
}
}

Related

How can I remove the CORB warning?

Chrome was working until version 73. Now it is throwing me a CORB warning and stopping my chrome extension from running.
Here is my ajax jquery code, nothing special
$.ajax({
url: this.url + "api/users",
type: 'get',
data: { account_id: this.account_id(), user_id: this.user_id(), person_id: person_id },
success: function (data) {
//do stuff
}
});
I did notice that if I remove the x-content-type-options header so that it no longer reads "nosniff" I can get some Ajax requests to be returned but not others. Not sure if this means anything but I noticed that the json requests that returned an array worked but others did not.
remove_keys = %w(X-Content-Type-Options)
response.headers.delete_if{|key| remove_keys.include? key}
[{'id' : '123'}] <-worked
{'id' : '123'} <- did not work (not sure if means anything)
Full error from chrome
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://ideas.test/api/users?token=W9BDdoiKcXLWSHXWySnwdCV69jz2y&account_id=3098355&user_id=john%40gmail.com&person_id=21046915&sync=false&new=true with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Headers from response
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: x-auth_token
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
Access-Control-Allow-Origin: chrome-extension://mhikhjencpecbhelhjgdcgpdhlhdlhjh
Access-Control-Expose-Headers:
Access-Control-Max-Age: 1728000
Request Headers
Provisional headers are shown
Accept: */*
Origin: chrome-extension://mhikhjencpecbhelhjgdcgpdhlhdlhjh
Referer: https://3.basecamp.com/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36
How can I get the response body to be returned without chrome removing the body due to CORB?
I found a workaround. Might be an overkill for someone, but it took me 15 mins to fix everythiung. In your content script wrap all your ajax calls into a function:
Add ajaxGet function to your content script:
function ajaxGet(data){
return new Promise(function (resolve, reject) {
chrome.runtime.sendMessage({action: 'ajaxGet', data: data}, function (response) {
console.log(response)
if(response&&!response.statusText){//Might need some work here
resolve(response);
} else {
reject(response)
}
});
});
}
And in your background.js add a listener:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.action=="ajaxGet"){
$.ajax(request.data).then(sendResponse,sendResponse)
return true //telling chrome to wait till your ajax call resolves
}
})
in stead of
$.ajax({
url: this.url + "api/user_boards",
type: 'get',
data: { account_id: this.account_id()}
})
call
ajaxGet({
url: this.url + "api/user_boards",
type: 'get',
data: { account_id: this.account_id()}
}).then(onSuccess, onError) //handle response from here
If you don't want to use jquery in your background.js you can make Xhr call in stead. Something like this:
var data = JSON.stringify(false);
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
sendResponse(this.responseText)
} else {
//handle errors
}
});
xhr.open("GET", request.data.url);
xhr.send(data);
You'll have to work around headers on your own.
It looks like you're putting the CORS headers in the request. You need to put them in the response instead.
Chrome 73 inject some new security. Just try to move your xHTTP requests to your background script with chrome.runtime.sendMessage and get response with SendResponse callback.
In content or popup script replace ajax with :
chrome.runtime.sendMessage(
{ action: "check", data: {/* params for url */}},
// callback with url response
function(response) {
if( response.success ) {
var myDataFromUrl = response.data;
...
} else {
console.log('Error with `check`,', response.data);
}
}
);
From background script:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
var url = 'https://mysyte.com/';
if(request.action === 'check' ) {
url = url + 'check'
ajax( url, request.data,
success: function( d ) {
sendResponse({success: true, data: d});
},
error : function( d ) {
sendResponse({success: false, data: d});
}
);
}
});
function ajax( url, params, cbSuccess, cbError ) { ... }
After fixing the CSP & CORS issues, I was still getting the warning on the OPTIONS method call (which is done for cross-domain calls).
I fixed it on the server by setting the content-type for the OPTIONS method call (which doesn't return any data) to "application/octet-stream". No more warnings!

Javascript Fetch API: header params not working

This is my sample request:
var header = new Headers({
'Platform-Version': 1,
'App-Version': 1,
'Platform': 'FrontEnd'
});
var myInit = {
method : 'GET',
headers: header,
mode : 'no-cors',
cache : 'default'
}
fetch('http://localhost:3000/api/front_end/v1/login', myInit)
.then(res => {
console.log(res.text())
})
When I debug, I see that this request is sent successfully to server, but server hasn't received header params (in this case is Platform-Version, App-Version and Platform). Please tell me which part do I config wrong.
thanks
You are using it correctly, but you have to tell your backend service to allow custom headers (X-). For example, in PHP:
header("Access-Control-Allow-Headers: X-Requested-With");
Also, your custom headers should be prefixed with X-. So you should have:
'X-Platform-Version': '1'
And one last thing, your mode needs to be cors.
You can see that standard headers are being sent with the following code. take a look at the network tab to see the standard request headers.
var header = new Headers();
// Your server does not currently allow this one
header.append('X-Platform-Version', 1);
// You will see this one in the log in the network tab
header.append("Content-Type", "text/plain");
var myInit = {
method: 'GET',
headers: header,
mode: 'cors',
cache: 'default'
}
fetch('http://localhost:3000/api/front_end/v1/login', myInit)
.then(res => {
console.log(res.text())
});

How to disable 'withCredentials' in api call using node.js only (https package)

I'm using a node.js script that load in-built https package. When using it I get error:
XMLHttpRequest cannot load [constructed-api-url]. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:3000' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
I'm using node.js 4.4.3, and its https api docs does not really mention anything about withCredentials.
The script being used is this one.
Is there anyway to set the xhr call's withCredentials to false using node.js https?
I am looking to something analogous to this jquery ajax call (just focusing on the xhr field):
$.ajax({
type: 'POST', async:true,
url: 'https://someapp.constructed.url/token',
dataType: "json",
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
xhrFields: {
withCredentials: true
},
headers: {
'Authorization': 'Basic ' + appInfo
},
success: function (result) {
var token = result.access_token;
//…
},
error: function (req, status, error) {
if (typeof(req) != 'undefined') {
var msg = status || req.responseJSON.error;
//…
}
}
});
There is another very similar example, but this is related to the request package, which I don't want to include in dependencies. Beside, my used script is already using https.
So the answer was there all the time, after all:
After a bit of research, found that node's https package uses practically same options as http, including the withCredentials option (not documented in node's http/https, but part of xhr documentation). It was a matter of including the url option within the options object along the withCredentials option, and then pass the options object as parameter for https.get.
And the constructed code would be more or less as follows (focus on the options variable):
var options = {
url: 'https://my.domain.com/api/endpoint',
withCredentials: false
}
var querystring = '?key=' + [_my_api_key];
var param1 = '&' + [paramKey] + '=' + [paramValue];
var datos;
options.url += querystring;
options.url += param1;
https.get(options, function (res) {
res.on('data', function (data) {
datos += data;
});
res.on('end', function () {
try {
var data = JSON.parse(datos);
} catch (e) {
console.error('Unable to parse response as JSON', e);
}
});
}).on('error', function (e) {
console.error('An error occurred with the request:', e.message);
callback(e.message);
});

firefox addon main.js is showing same request response, not updating

What I'm doing wrong with addon builder? , it is not showing new request response, it show same response all the time, here is my code for main.js :
var tmr = require('timer');
var timus=5000;
var Request = require("sdk/request").Request;
function timer_restarting(){
gint = tmr.setInterval(function() {
Request({
url: "http://mysite.com/data.txt",
onComplete: function (response) {
if(response.text.indexOf('<show>true</show>')>-1){
timus = parseInt(response.text.substring(response.text.indexOf('<interval>')+10,response.text.indexOf('</interval>')));
show(response.text.substring(response.text.indexOf('<message>')+9,response.text.indexOf('</message>')));
tmr.clearInterval(gint);
timer_restarting();
}
}
}).get();
}, timus);
}
timer_restarting();
the addon show every 5 sec same message, it is not updating . I have an impression like it is not doing new request to server. I have changed message but it still show old message. what is the issue?
please
UPDATE:
if I will manually go to that link in browser and refresh it, then addon will refresh the respone as well. Why is that happening ?
Try adding a header for 'Cache-control' to your Request instance, and specify a value of 'no-cache' (or some 'max-age' value), to prevent getting a cached response.
E.g. in your example, between the lines
url: "http://mysite.com/data.txt",
onComplete: function (response) { /* ... */ }
insert the following lines:
url: "http://mysite.com/data.txt",
headers: {
'Cache-control': 'no-cache'
},
onComplete: function (response) { /* ... */ }

Cross domain jQuery ajax calls not working

I'm having trouble with this code and I can't seem to get it to work. The typical error that I get back for this call is a "Failed to load resource: the server responded with a status of 401 (Unauthorized) " .
$('#btnZendesk').click(function () {
$.ajax({
url: "https://flatlandsoftware.zendesk.com/api/v2/topics/22505987.json",
type: 'GET',
crossDomain: true,
xhrFields: {
withCredentials: true
},
cache: false,
dataType: 'jsonp',
processData: false,
data: 'get=login',
timeout: 2000,
username: "test#test.com",
password: "test",
success: function (data, textStatus, response) {
alert("success");
},
error: function (data, textStatus, response) {
alert(data);
}
});
Problem is that the resource you are trying to access is protected with Basic Authentication.
You can use beforeSend in jQuery callback to add a HTTP header with the authentication details e.g.:
beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Basic XXXXXX");
}
Alternatively you can do it using jQuery ajaxSetup
$.ajaxSetup({
headers: { 'Authorization': "Basic XXXXX" }
});
EDIT
A few links to the mentioned functions
jQuery.ajaxSetup
jQuery.ajax
EDIT 2
The Authorization header is constructed as follows:
Username and password are joined into a string "username:password" and the result string is encoded using Base64
Example:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
I too got this problem and somehow all solutions from internet either failed or were not applicable due to client webservice restrictions (JSONP, XDR, CORS=true)
For this, I added an iframe in my page which resided in the client;s server. So when we post our data to the iframe and the iframe then posts it to the webservice. Hence the cross-domain referencing is eliminated.
We added a 2-way origin check to confirm only authorized page posts data to and from the iframe.
Hope it helps
<iframe style="display:none;" id='receiver' name="receiver" src="https://iframe-address-at-client-server">
</iframe>
//send data to iframe
var hiddenFrame = document.getElementById('receiver').contentWindow;
hiddenFrame.postMessage(JSON.stringify(message), 'https://client-server-url');
//The iframe receives the data using the code:
window.onload = function () {
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
var origin = e.origin;
//if origin not in pre-defined list, break and return
var messageFromParent = JSON.parse(e.data);
var json = messageFromParent.data;
//send json to web service using AJAX
//return the response back to source
e.source.postMessage(JSON.stringify(aJAXResponse), e.origin);
}, false);
}

Categories

Resources