Cookie Access over JSONP - ajax

I have a page in domain.com that makes a JSONP ajax request (using jQuery's .getJSON() function) to a URL in anotherdomain.com. I thought (read: assumed) that the resource in anotherdomain.com would have server-side access to any cookies set in that domain, but that doesn't seem to be the case?
The ajax call is being done specifically to access a particular cookie, do some data manipulation and return a rich set of information keyed by the cookie value. The original domain doesn't have direct access to the cookie value, so I thought that an ajax request would maintain the state I need.
Which pivotal piece of information about cookies am I overlooking? I'm exhausted and I'm just not seeing it.
Thanks.
UPDATE
I found a way of doing it, but it looks like JSONP to my eye, so I'm wondering why this way works while the Ajax version doesn't. Is the request just disconnected from the browser session so that no cookies are accessible?
<script type="application/x-javascript" src="<?php echo $service_url . '&callback=interests' ?>"></script>
<script type="text/javascript">
function interests( data ) {
$( function() {
var c_behaviors = data.length;
var ids = [];
for( var i = 0; i < c_behaviors; i++ ) {
ids.push( data[i].behavior_id );
}
$('body').append( '<p><label>Returned:</label> ' + ids.join( ', ' ) + '</p>' );
});
}
</script>

The same origin policy applies to all ajax requests, so if the domain being accessed in an ajax call is different than the domain loaded in the browser (document.host), all cookies associated with the domain in the requested url will not be sent up. Therefore, the JSONP approach works because it writes out a new script tag in the window, which will behave like any resource request a browser could make to an external domain (hence passing all the cookies associated with the domain in the url). I have also confirmed this by simply calling $.post("http://atdmt.com") from my chrome console, while on stackoverflow.com in the browser (the only other domain that had cookies in my browser, while writing up the answer) and it did not send up any cookies in the request headers.
Another solution to get around the problem of maintaining state for anotherdomain.com would be to have anotherdomain.com set a first party cookie (by not setting the domain attribute of the cookie) and when an ajax/json request is made to anotherdomain.com access those cookies via javascript and push them up the request using standard HTTP params.
Hope I have helped.

I have encountered the same problem before. The issue I found is that most browsers won't let you ESTABLISH a session (i.e. set a session cookie) when the same origin policy isn't being met.

Related

Ajax login to a website and follow redirect

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.

XHR Get Request not passing Google Chromestore Checks

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.");

How to get cookies from Ajax / xmlhttprequest call's response

My application is making a network call using xmlHttpRequest. In the response i am getting Set-Cookie header (verified with fiddler). I need to access these cookies from javasript. I tried with XmlHttpRequest.getAllResponseHeaders(), it is returning all headers except Set-Cookie.
Is there a way to access these cookies from javascript? If yes, please provide some example.
My application is running on Webbrowser control (IE10), Windows Phone 8.
Thanks in advance.
While awaiting a more specific answer, you can instead send all the cookies set from the server through a post response, then set it locally, as so (using jQuery to make it easier):
// Client
var cookie;
$.post('example.com',{'stuff':'data'},function(data){
cookie = data;
});
// Server
if(isset($_POST['stuff'])) echo WhateverTheCookieWouldBe;
Actually cookies can be accessed via
document.cookie // this will return a string contains all cookie values separated by semicolon
This is actually not true since because of the async nature of request
// Client
var cookie;
$.post('example.com',{'stuff':'data'},function(data){
cookie = data;
});
alert(cookie); // undefined

Remove cookies from jquery ajax calls

I would do jquery ajax calls discarding every cookie, so I can have a new session for every call.
Is there a way to do this?
Thanks
AJAX request is exactly an HTTP request (XMLHTTPRequest). Cookies get sent back and forth in the AJAX request-response headers in order to maintain the state of user session across multiple HTTP requests.
HTTP is an inherently stateless protocol and hence cookies are used to maintain the state of user's session across multiple HTTP requests.
Instead of removing cookies host all your static components(like images) in a Cookie-free Domain. The following url might might give you some info in this,
http://www.ravelrumba.com/blog/static-cookieless-domain/
As Harun pointed out, maybe you should consider a wider solution than deleting a session cookie that will alter the whole user session and not only your AJAX call.
To litteraly answer your question, you could delete the cookie you've set (provided you've set by yourself and not by another framework):
$.cookie("session", null);
$.ajax( url, [settings] )
But, that's probably not the good solution because you will delete the whole user session at each ajax call. You should tell us more about what you are doing so that we could help you.

phonegap: cookie based authentication (PHP) not working [webview]

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();

Resources