Chrome extension Cross Domain Request - javascript

I know that this has been talked about many times here, and I have read most of these threads but I can't seem to get my script working.
Problem is that I am trying to use bitly api to shorten urls in google chrome extension. I am saving users login and apiKey in localstorage and before I do so I validate them.
The code to do so is:
$.ajax({
url:"http://api.bit.ly/v3/validate",
dataType:'jsonp',
data:{
login: login,
apiKey: apiKey,
x_login :"test",
x_apiKey :"test"
},
success:function (jo, textStatus, jqXHR) {
if (jo.status_code == 200) {
setItem('dg_BitlyApiKey', apiKey);
setItem('dg_BitlyLogin', login);
alert('Saved');
} else {
alert('Incorrect login and/or apiKey!')
}
}
});
I do have my permissions set to "permissions": ["tabs", "notifications", "http://*/*", "https://*/*"] but I still keep getting:
Refused to load script from 'http://api.bit.ly/v3/validate?callback=jQuery17204477599645033479_1334062200771&login=&apiKey=&x_login=test&x_apiKey=test&_=1334062201506' because of Content-Security-Policy.
The script itself works outside the extension so I assume the problem isn't within the script but with the permissions.
What am I doing wrong here?

The problem is that you aren't really doing a XHR request, you're doing a JSONP request on an insecure HTTP resource. See the question How to load an external JavaScript inside an extension popup and the related Chromium bug report.
Yeah, we're no longer allowing insecure scripts in extensions. If you load a script over HTTP, an active network attacker can inject script into your extension, which is a security vulnerability.
JSONP operates by dynamically adding a new script tag into your page and then executing the contents. In your case, the script resource is fetched over HTTP (instead of HTTPS). If your extension uses version 2 of the extension manifest, its background pages cannot fetch non-HTTPS scripts.
Solution: If you use the Bitly API over HTTPS, I believe that will fix your issue. Send your Ajax call to https://api-ssl.bitly.com/v3/validate (instead of your current value of http://api.bit.ly/v3/validate)

You need to package your app/extension for cross domain requests to work. A hosted application will not be able to do cross domain requests. See:
Cross-Origin XMLHttpRequest in chrome extensions

To make Cross-Origin Requests in Chrome Extension you need to Avoid Cross-Origin Fetches in Content Scripts.
Full answer you can found in
https://stackoverflow.com/a/56929473/3680164
Or in the documentation
https://www.chromium.org/Home/chromium-security/extension-content-script-fetches

Related

Resolve "No 'Access-Control-Allow-Origin' header is present" issue with Chrome Extension

I am developing a Chrome Extension that pre-populates fields then submits the form on an external website when I visit it.
It works perfectly when the data is hard-coded into my script.js file.
However, I'd like to grab the username from an element in my Intranet home page & use this in the script instead of hard coding it.
I have made a simple script.js to test this works:
script.js:
$.get('https://intranet/index.php', function(data){
alert('test');
});
When I try to use this in my Extension and reload the page, I get the error:
XMLHttpRequest cannot load https://intranet/index.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'chrome-extension://eecikfibchjhmochelhmhlimbcjglldf' is therefore not allowed access. The response had HTTP status code 401.
When this same code is run at https://intranet/test.html it works perfectly.
test.html:
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
</head>
<script type="text/javascript">
$.get('https://intranet/index.php', function(data){
$(document.body).load('https://intranet/ #username');
});
</script>
index.php:
<?php
header("Access-Control-Allow-Origin: *");
echo '<div id="username">username</div>';
?>
I have read that some use JSONP to resolve this issue. Does anyone have experience of this?
Can anyone provide help/advice on this issue?
Thank you for any guidance.
There seem to be two issues here at once.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Doesn't look like you thoroughly searched for solutions, since it's a common problem. Anyway, there are 2 ways to solve this:
On the extension side. If you have host permissions, you can do cross-origin requests regardless of CORS headers. (note: "When this same code is run at https://intranet/test.html it works perfectly" highlights that the issue is cross-origin but works on the same site).
There's a whole extension documentation article on this: Cross-Origin XMLHttpRequest, but an ultra-short version: you need to add permissions for the site in the manifest:
"permissions": [
"https://intranet/*"
],
On the server side, by adding a Access-Control-Allow-Origin: * header. Note that this solution opens a certain attack surface (not only your extension can do requests now), so approach 1 is preferable.
That said: you tried to implement approach 2, and it didn't work. Why? Because there is a second problem:
The response had HTTP status code 401
HTTP 401 is "Unauthorized". Your requests lack the authorization necessary - which you don't see when using the intranet site itself, since the browser already have those credentials cached.
But they won't be applied to cross-origin requests, so you get a 401 error page instead of the intended page - that doesn't contain your header.
You need to provide authorization along with the request. jQuery allows that:
$.get(
{
url: 'https://intranet/index.php',
username: '...',
password: '...'
}, function(data){
alert('test');
}
);
I think it should be obvious that this shouldn't be hardcoded in the extension.

Chrome extension Background and content script posting message

I have a content script which includes jquery ui component and i want to send data to my server with http post. However i have come to realize that you can not send http post message to a https website or vice versa. If i send my message to the background script and post from there will i have a problem about it? Will it make a difference if the site is http or https? If it makes a difference how can i get this done?
Yes, you can use http POST, as well as any other http method (e.g., GET, PUT, PATCH), in a content script -- as well as a background script, for that matter.
However, in both cases, the URL to which you're sending your request must be declared in your extension's permissions. You do this in the manifest. For example, if you would like to send http requests to http://www.some-domain.com, you must add that URL (or a pattern matching that URL) to the permissions array of your manifest:
{
...
"permissions": [
"http://www.some-domain.com/*"
],
"name": "Test",
"manifest_version": 2,
"version": "0.0.0"
}
You can add wild cards to your URL permission patterns; thus, if you'd like to match both https and http, you can do something like *://www.some-domain.com/*. See the official literature here.
I should warn you that if you are attaching a content script to a page that was loaded as https rather than http, you will likely not be allowed to send an unsecure http request due to Chrome blocking mixed content, which I believe requires a user override. So a good rule of thumb is: if you're attaching your content script to a page loaded via http, then use http to send the request; if you're attaching to a page loaded via https, then use https.
One last tip: Don't forget to reload your extension after you've changed the manifest, or the permission changes won't be reflected. To reload your extension, go to chrome://extensions, find your extension, then hit reload.
If you send from your background script there is no problem with switching protocols but you had to declare permission to these urls:
see more at the google manifest documentation and this duplicated question

Access-Control-Allow-Origin in Google Safe Browsing API

I have a script which I give to my clients and they put it in their web pages.
I want to check inside that script if the domain is safe using Google's Safe Browsing API.
When the script loads, I make an API request for the current domain with the client key I got from Google.
"Client key" according to Google:
API requests are sent directly to Google from your clients' browsers
$.ajax({
url: "https://sb-ssl.google.com/safebrowsing/api/lookup?client=demo-app&key=AIzaSyBx5EyJlhg-oB4inoO15fMlP37ljeDP98o&appver=1.5.2&pver=3.1&url=http%3A%2F%2Fstackoverflow.com",
method: "GET",
success: function (result) {
self.onDataReceived(result);
}
});
But the browser blocks my request due to No 'Access-Control-Allow-Origin' header is present on the requested resource.
It appears that the Safe Browsing API does not support cross origin requests and your best option is running a proxy on your domain.

Adobe Connect API with Jquery

I am trying to create a simple login form for my Adobe Connect account, however it's not working, I'm getting the error:
No 'Access-Control-Allow-Origin' header
However I'm doing other Ajax calls just fine on my machine.
Here's some example code that I'm using.
var request $.ajax({
url: 'http://example.com/api/xml?action=login&login=' + username + '&password=' + password
type: "GET"
});
request.done(function(){
...
})
Does anyone have any suggestions?
Your local machine calls are working because you're making calls inside the same domain. As soon as you try to do ajax calls to something outside the bounds of the caller's domain you'll run into issues with the browser's Same-Origin policy.
Basically it's a security policy that allows scripts to run on pages originating from the same site (comprised by the combination between schema, hostname and port. eg. mysite != mysite:8080) So if you have an ajax call executed from a site running on mysite to a site running on mysite:8080, the browser will consider this a same-origin policy hence blocking that request.
You should read about CORS (Cross-Origin Resource Sharing) in order to find options to help you relax the same-origin policy.

how Postman send requests? ajax, same origin policy

I have found this very useful Chrome extension called Postman. This is a very useful extension especially when you are into programming RESTful applications.
One thing I am confused on is that how this plugin/extension able to send POST request successfully on different domains?
I tried voting in a poll using Postman like this.
After submitting that, the vote was actually counted in, but when I tried doing that using AJAX and JavaScript, it fails, because of different origin policy of browsers.
How is that even possible?
Here is my code using jQuery. I used that in my computer though, localhost.
init: function() {
$.ajax({
url: 'http://example.com/vote.php',
type:'POST',
dataType: 'html',
data: {
id: '1'
},
success: function(data) {
if ( data == 'voted' ) {
$('.set-result').html( 'you already voted. try again after 24 hours' );
} else {
$('.set-result').html( 'successfully voted' );
}
}
});
},
Chrome packaged apps can have cross domain permissions. When you install Postman it promts you that this app will access any domain.
By placing */* in permissions section of your manifest file, you can do this.
Read more here:
https://developer.chrome.com/extensions/xhr.html
You can add the following header to sent Ajax request in postman.
Content-Type application/json
X-Requested-With XMLHttpRequest
Screenshot
Sounds like the site that hosts the poll (the "vote.php" script) needs to have an "Access-Control-Allow-Origin" header set to allow posting from a list of sites (or all sites).
A value of * for the header will allow posting from any website:
Access-Control-Allow-Origin: *
i.e. You could put the following at the top of vote.php
header('Access-Control-Allow-Origin: *');
Chrome extensions and apps are not subject to the same security limitations placed on normal webpages.
Additional debugging tips:
If you're trying to access remote services from web pages you have open on your local file system in your browser, you might find your browser applies different security rules to them than it does to files served from a web service.
e.g. If you open local files from a locational like C:\MyDocuments\weboot\index.htm (Windows) or \Users\joe\Sites\index.html (Mac) in your browser your AJAX request might not work, even with the header specified in most browsers.
Apple's Safari applies almost no cross domain restrictions to files opened locally but Firefox is much more strict about what it permits, with Chrome somewhere in the middle. Running a web server locally (e.g. on http://localhost/) is a good idea to avoid unexpected behaviour.
Additionally, other libraries that provide functions to handle Ajax requests (such as AngularJS) may require other headers to be set on the server by default. You can usually see the reason for failure in a browser debug console.
2021 Oct
In my investigation, I found out that you need an extra field in the header of your request. So simply add the following key-value into the header:
key: X-Requested-With | value: XMLHttpRequest

Categories

Resources