We've built a very lightweight simple Chrome extension for our customers, its private and won't be made publicly available but due to restrictions by Google now needs to at least exist privately on their store.
The idea of the extension is to automatically track cashback opportunities for our clients computers. It does this by checking each new URL they visit just once against our API - if its not a shopping site that exists (eg Facebook or Google) then storage makes sure that URL is never checked again, if it is, then its checked only once in a 24 hour period and the URL returned by the API is visited with an AJAX GET Request.
The get request loads the URL via the cashback site so it sets the correct cookies for the user automatically, in the background, without disrupting the users browsing session.
The extension though whilst accepted by Apple and Mozilla for Firefox and Safari is being rejected by Google and it appears to be due to our XHR request - though they sent the same generic rejection request and it appears its being rejected via an automatic check - it appears whats being flagged up is that the GET request could be request external javascript (eg malicious stuff) from 3rd parties and of course all code (and quite rightly) needs to be within the extension itself.
They provide examples of using cross-origin calls on their site here https://developer.chrome.com/extensions/xhr
As we only need to set the cookies from the URL we visit, would there be anyway to filter the get request to abide by their security rules and instead of just downloading everything from the URL we'd block downloading external javascript libraries etc?
This is well beyond my realms of coding here so i'm more interested if anyone could think of a way we COULD do this that would pass Google's checks - ultimately the AJAX request we do just loads the website they are already on, but as its going via a tracking company to set the cookie it will of course call on a couple of simple redirects first usually to set the session ID. If its possible for us to still use this data whilst making it pass Google checks, i'm not sure.
Here is a snippet of current XHR related code
kango.xhr.send(details, function(data) {
if (data.status == 200 && data.response != null) {
var text = data.response;
console.log(window.location.href);
kango.console.log("THE RESPONSE URL: " + text);
var affilDetails = {
method: 'GET',
url: text,
async: true,
contentType: 'text'
};
and
kango.xhr.send(affilDetails, function (afilData) {
console.log(thisDomain + " expire updated to " + new Date(expireshort));
if (afilData.status == 200 && afilData.response != null) {
kango.storage.setItem(thisDomain,expireshort);
console.log("RESPONSE URL HAS BEEN VISITED VIA AJAX.");
Related
I want to login to a website and follow redirection whit ajax or XMLHttpRequest or any thing else exept php.
Actually whene i try to do it, i have error "302 Moved Temporarily" but the webpage is the right page so i don't know why i get this error.
The website is an external website (not on my server).
This is my code :
$.ajax({
type: "POST",
contentType: "application/x-www-form-urlencoded",
url: "http://website/index.php",
data: { username: "myuser", password: "123456" },
success: function(data) {
console.log("success ", data.response);
},
error: function(data) {
console.log("error ", data.error);
},
dataType: "html"
});
If you try use ajax outside your domain, you will probably get this error message:
XMLHttpRequest cannot load http://www.example.com/path/filename. Origin
null is not allowed by Access-Control-Allow-Origin.
The reason you get this error message is because of the Same-origin policy. The policy permits scripts running on pages originating from the same site to access each other's data with no specific restrictions, but prevents scripts access to data that is stored on a different domain.
This could be a problem if you are trying to access publicly hosted data, but there are ways around it.
Here is the list of methods:
Implement CORS (Cross-Origin Resource Sharing)
Use JSONP (JSON Padding)
Use postMessage method
Setting up a local proxy
CORS (Cross-Origin Resource Sharing)
CORS is a mechanism that allows resources on a web page to be requested from another domain outside the domain the resource originated from. In particular, JavaScript's AJAX calls can use the XMLHttpRequest mechanism. Such "cross-domain" requests would otherwise be forbidden by web browsers, per the same origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request. It is more useful than only allowing same-origin requests, but it is more secure than simply allowing all such cross-origin requests.
JSONP (JSON Padding)
JSONP or "JSON with padding" is a communication technique used in JavaScript programs running in web browsers to request data from a server in a different domain, something prohibited by typical web browsers because of the same-origin policy. JSONP takes advantage of the fact that browsers do not enforce the same-origin policy on <script> tags.
Because of the same origin policy, we can not make cross domain AJAX requests, but we can have <script> tags that load javascript files from other domains. JSONP uses this exception in order to make cross domain requests by dynamically creating a <script> tag with necessary URL.
postMessage method
window.postMessage method is part of HTML5 introductions. It allows communication between window frames without being subject to same origin policy. Using postMessage() one can trigger a message event with attached data on another window, even if the window has different domain, port or a protocol. The frame where the event is triggered must add an event listener in order to be able to respond.
Let's see an example. Assume, we are on http://example.com (1) website and would like to make a request to http://example2.net (2) domain. We first must obtain a reference to (2) window. This can be either iframe.contentWindow, window.open, or window.frames[]. For our case it's best to create a hidden iframe element and send messages to it.
Setup local proxy
This method overcomes same origin policy by proxying content on another domain through itself. Thus making cross-domain issue irrelevant. To use this method you will either a) setup your server as a reverse proxy to fetch content from another server or b) write a script that would do that.
This cross domain querying solution works because you actually loading content from your own domain. You request the URL and the proxy script on your server loads the content and passes it over to you.
http://www.ajax-cross-origin.com/how.html You can visit this link if you want to learn about these methods in details. There is also a jquery plugin named ajax cross origin to tackle similar issues.
For some reason the mobile authentication detection stoped working. When I access a location containing a form on my page, the form should call (via ajax) for additional information to fill the fields, the server returns depending on user authentification. It worked well for nine months, but stoped working for mobile devices, however it still works for desktop browser access. Mobile and desktop use exactly the same access route, arguments, urls, view function ... everything. The one difference that I noted (after some 8 hours on this issue) when I looked up the request.META, is that desktop sends cookie information, mobile doesn't. However cookies are enabled on mobile and desktop browser. I tested this with Chrome mobile and (a freshly installed) Firefox on mobile, the result is exactly the same.
How is this possible? Why does the form when initializing on desktop send the cookie info and when initializing on mobile don't send it?
Here is a previous version of this question (written before I noticed the cookie difference and thought it was an api issue) containing technical details that I don't consider to be relevant for the particular question of how does the same functionality behave some differently on mobile and desktop.
EDIT: I really don't know what code to show, but probably the ajax request could be relevant. I am really lost here. This is the react-js service I use to load form initials, it's the one that arrives without cookie information when send form mobile device, and with cookie if send from desktop device, to the server. I am not aware to have added anything or changed this in anyway in the past nine months, it always worked only like this:
loadFormInitials = (typ,genderRelevant,auth) => {
$.ajax({
url: UserConstants.BASE_URL+'elements/?item=setup&auth='+auth,
method: 'GET',
dataType: 'json',
success: (result) => {
var data = JSON.parse(result.initial_data);
FormActions.loadFormInitialsAction(data,typ,genderRelevant);
});
}
Mobile companies sometime alter HTTP requests with their heavy caching.
You'd probably want to try again with HTTPS requests, not sure it'll fix though.
I've an API endpoint hosted (built via Django Rest Framework), for eg:- domain.com/api/fetch_all?start=0&end=50. This fetches all the results from the database in a pagination manner.
Now I'm representing this information on a webpage. Its more or less like an open forum where everyone can read the data, but only some can write. I'm viewing this data onto the webpage via an AJAX request hitting the above endpoint. For eg:-
$.ajax({
type:'get',
contentType: 'application/json',
url:'domain.com/api/fetch_all?start=0&end=50',
cache : true,
dataType:'json',
success:function(data)
{
// presenting the information when the page loads.
}
});
So, my questing is how can I secure my APIs, so that no robots can access the data that I'm presenting on my forum. For eg:- if any code/script tries to access my APIs, it should throw 403 Forbidden error.
import requests
# this should return 403 error
response = requests.get('domain.com/api/fetch_all?start=0&end=50')
However, if I try to get this data via the browser AJAX request, it should return the data. How can I make sure whether the request is coming from a browser(man-handled) or a robot?
PS: I cannot add OAuth functionality over here, since I dont have a login form.
It's not possible to restrict requesters in this way, because a robot could always add headers to spoof being a browser. Anything you do on your client can be copied by an attacker. Without requiring auth, the best you can do is rate limiting - track requests on a per-client basis, and only allow a certain number of requests per time unit.
A partially-functional solution would be to look at the User-Agent header. That should include browser information, and might let you knock out some robots, but not all or even most of them.
Recently I got to the point to host a static webpage with a subscription option on aws s3 while website development is undergoing. My static web page makes an ajax call to another RESTful service with an email of a subscriber as a parameter. When subscription is done I need to notify a subscriber. Here it seams an issue with the callback.
$.ajax({
type: 'GET',
url: 'http://www.my-domain.com/api/Subscribe?email=' + email
}).success(function (data) {
if (data) {
alert('Thank you for registering!');
}
});
After subscription is done ".success(" doesn't fire up. Response on the request is:
Reload the page to get source for: http://www.my-domain.com/api/Subscribe?email=john.smith#simplyemail.com
Does anyone know if it's an s3 feature or something else?
As per your description this seems to be related with CORS policy.
Look to "why CORS" as Amazon defines it:
In order to keep your content safe, your web browser implements something called the same origin policy.
The default policy ensures that scripts and other active content
loaded from one site or domain cannot interfere or interact with
content from another location without an explicit indication that this
is the desired behavior.
In certain cases, the developer of the original page might have
legitimate reasons to write code that interacts with content or
services at other locations. CORS provides the mechanism to allow the
developer to tell the browser to allow this interaction.
I understood that:
[...] ajax call to another RESTful service[...]
Means call to another server, and this may be blocked by Browser because of CORS.
References:
Mozilla
W3C
I'm working on a mobile web-app using sencha touch, HTML5 and phonegap as a wrapper.
I'm using PHP-Authentication (Cookie) and ajax-requests. Everything works fine on safari or chrome, but after the deployment with phonegap (webview) it does't work anymore...
Any help would be appreciated :)
Some more details:
All data for my app is loaded via ajax requests to my server component "mobile.php".
I use basic PHP-Auth to autenticate the user:
AJAX-Request [username, password] -> mobile.php
-> Session established (cookie)
All other requests if auth was successful
What's the difference between a normal safari website and the webview?
i figured it out:
you have to change the phonegap_delegate.m file and add the following to the init method:
- (id) init
{
/** If you need to do any extra app-specific initialization, you can do it here
* -jm
**/
//special setting to accept cookies via ajax-request
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage
sharedHTTPCookieStorage];
[cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
return [super init];
}
it enables webview to accept cookies from ajax requests
If your Phonegap AJAX requests are not firing callbacks like they're supposed to, this may be the reason.
If the response you're getting attempts to set cookies and you haven't done Michael's fix then your (jquery) AJAX request will fail quietly -- neither success: nor error: callbacks will fire despite the fact that the server actually received the request and sent a response. It appears you must do this even if you don't care about the cookies.
I hope this helps someone.
I didn't care about the cookies but just spent a few hours trying to figure out why the callbacks didn't fire!
There is a solution that works on android too:
Install plugin https://github.com/wymsee/cordova-HTTP to perform arbitrary HTTP(S) requests.
Replace XMLHttpRequest with the plugin alternative (cordovaHTTP.get or cordovaHTTP.post):
cordovaHTTP.post("https://example.com/login", {email: 'xyz#example.com', passwd: "s3cr3t"}, {}, function(response) {
console.log('success');
console.log(response);
}, function(response) {
console.log('failure');
console.log(response);
});
The response will contain status, data and response.headers["Set-Cookie"], that can be parsed for name, value, domain, path and even HttpOnly flags ;-)
Said cookie can be saved in LocalStorage and sent in subsequent requests (see cordovaHTTP.setHeader() or header parameter of .get/.post methods) to simulate an authenticated user on a desktop browser.
Best ways to store get and delete cookie its working fine in my app which is on live
To store value in cookie
window.localStorage.setItem("key", "value");
To Get value in cookie
var value = window.localStorage.getItem("key");
To Delete cookie value
window.localStorage.removeItem("key");
window.localStorage.clear();