Navigating cross domain JSONP cookies in IE8 to IE10 can be a real headache

For reasons completely out of my control, here is the current scenario I'm faced with:

  • I have a product listing on catalog.org

  • When you click the "Add to Cart" button on a product, it triggers an AJAX JSONP request to secure.com/product/add/[productKey]. This action saves the cart record to the database, sets a cookie containing the cart ID, and returns either true or false based on success

  • If the response is true, another AJAX JSONP request is made to secure.com/cart/info on catalog.org. This request reads the cart ID cookie, retrieves the record, and shows the number of items in the cart

  • Upon receiving the response back on catalog.org, the number of items in the cart (if any) is displayed by updating an element on the page

  • Clicking the "Go to Cart" button on catalog.org then reveals the cart summary on secure.com

This setup functions flawlessly on Firefox 17, Chrome 32, and IE 11, as well as on our development and test platforms where catalog.org is catalog.development.com/test.com and secure.com is secure.development.com/test.com respectively.

However, once we deployed to production, this system ceased to work properly on IE8 - IE10. After adding a product to the cart, the item count updates correctly on catalog.org but fails to display on the cart summary page on secure.com due to an inability to read the cookie. Despite setting a P3P compact policy header on all requests from secure.com, the cookie remains unset. The header we implemented looks like this:

P3P: CP="CAO PSA OUR"

Why hasn't introducing the compact policy header resolved the issue on IE8 - IE10? How can I rectify this across all versions of Internet Explorer?

Solution

There are numerous suggestions listed below, with @sdecima's being selected for its promise. We amalgamated some of these ideas, avoiding XDomainRequest altogether:

  • By clicking the "Add to Cart" button, an AJAX JSONP request is sent to secure.com/product/add/[productKey]. In response, the request returns a JSON object signaling either success or failure as well as the cart ID

The next step was altering the action at secure.com/product/add to handle the returned JSON object properties accordingly.

  • Following a successful response on catalog.org, another AJAX JSONP request is dispatched to secure.com/cart/info. This request reads the cart ID cookie and gathers information about the cart, revealing the item count

We adjusted the callback function to cater to both response object properties. If the success flag is true and the cart ID exists, a hidden iframe is generated on the page. The iframe's src attribute points to a new endpoint added to secure.com. This action takes a cart ID parameter and sets the cart ID cookie. Consequently, the necessity to set the cookie during the secure.com/product/add action diminishes.

Subsequently, we revised the action at secure.com/cart/info to accept a cart ID parameter. When available, this action utilizes the cart ID provided to fetch the cart details; otherwise, it resorts to attempting to read the cookie. This additional check would be redundant if we could ensure that the iframe had completed loading and the cookie had been saved on secure.com. Unfortunately, due to browser security restrictions, we lack certainty over when the iframe concludes loading on catalog.org.

Lastly, the P3P header CP="CAO PSA OUR" continues to be crucial for ensuring functionality across IE7 - IE10 browsers. (Yes, it now works on IE7 too :)

We've devised a solution (albeit complex) for storing and accessing cross-domain cookies that operates smoothly across major browsers, extending back as far as our reliable testing permits.

We may consider further refactoring. For instance, the second AJAX JSONP request to secure.com/cart/info is somewhat unnecessary given that we can retrieve all requisite data within the original request to secure.com/product/add action (beneficially, error messages indicating why the operation failed can also be returned).

Answer №1

In summary

For IE 8 and 9, cookies won't be transmitted in cross-origin requests. However, this limitation is not present in IE 10 and 11.


Regarding IE 8 and 9

In the case of IE8/9, XMLHttpRequest partially supports CORS, and although cross-origin requests can be made using the XDomainRequest object, it does not include cookies in the request.

More information on this topic can be found on the official MSDN Blog post:

Especially take note of this section:

5 . No authentication or cookies will be sent with the request

To avoid misuse of user credentials like cookies or HTTP credentials, XDomainRequests will remove any cookies and credentials, and will ignore authentication challenges or Set-Cookie directives in the response. XDomainRequests will also not be sent on connections that were previously authenticated due to certain Windows authentication protocols being connection-based rather than request-based.

Regarding IE 10+

Starting from IE10, full support for CORS was added to XMLHTTPRequest, allowing proper functionality with a correct Access-Control-Allow-Origin header set on the server response (which intends to store the cookie on the browser).

Further details can be found here:

And here:
http://www.html5rocks.com/en/tutorials/cors/

Workarounds for IE 8 and 9

The only workaround for IE8/9, as mentioned in the same MSDN article above:

Websites wanting to authenticate users for cross-origin requests can employ explicit methods (like tokens in the POST body or URL) to pass authentication information without risking user credentials.

Answer №2

It's crucial to remember that third party cookies are frequently blocked by privacy and advertisement blocking tools, making them unreliable for use. It's important to reconsider their usage in production.

The structure indicates that the endpoint may eventually transition to a RESTful design. However, incorporating cookies contradicts the essence of being "stateless." The recommended approach would be to modify the API instead. This is especially valid if there is no integration with a third party (e.g., when "secure.com" is managed internally within your organization).

To address the issue, it is suggested to transfer the cartId from the secure.com cookie to the query string:

secure.com/product/add/9876?cartId=1234    //preferably using a POST request

How can you obtain a legitimate cartId value? One option is to store it in a secure-com-cart-id cookie specifically for the catalog domain to avoid any cross-domain complications. Verify this value and add it to all secure.com requests as shown above:

$.post('secure.com/product/add/9876', {    //requires jQuery.cookie
  cartId: $.cookie('secure-com-cart-id')
});

If a valid cartId is not available, treat it as a new user and execute the request without the parameter. Subsequently, the API should assign a new id and return it in the response. Update the "local" secure-com-cart-id cookie accordingly. Repeat this process as needed.

This method allows for the persistence of an active user cart without relying on cookies for every API call. If altering the API structure or communication with the architect is not feasible, consider setting up a tunnel to the secure.com endpoint to prevent cross-domain requests. This could involve utilizing catalog.org/secure-com-endpoint to forward requests verbatim to secure.com. Implement proper server rules to manage this setup rather than resorting to coding solutions. Several resources provide insights into bypassing cross-domain restrictions, such as this one.

On a side note, this situation embodies a classic XY problem according to my perspective. The focus shouldn't just be on persisting third party cookies but on effectively transmitting essential parameters to a third party while retaining the data somewhere.

Answer №3

While a more permanent solution would involve changing the architecture, for a quick fix:

JSONP files are essentially just JavaScript. You have the option to insert a line of code setting cookies at the beginning of your JSONP file.

For instance instead of:

callback({"exampleKey": "exampleValue"});

Your JSONP could be modified to look like this:

document.cookie="cartID=1234";
callback({"exampleKey": "exampleValue"});

Answer №4

To ensure both servers are in the same domain, make a new entry in the DNS records if you have control over them.

Answer №5

Can one database serve both catalog.org and secure.com, enabling communication between them?

Indeed, it is possible.

Here's how it works: when a cookie is served by catalog.org, it is saved in the database. Similarly, when secure.com serves a cookie, it is also saved in the same database. This allows for tracking which user's cart belongs to whom.

Let's delve into this intriguing problem... Update 2:

When a user visits catalog.org:

  • First, check if they have a cat_org cookie. If not, then:

    • On catalog.org:

      • Generate a key-value pair and store it in the database {cat_cookie_id, unique_number}
      • Set cat_cookie_id in the browser
      • Instruct the browser to make an AJAX call to secure.com/register/unique_number
    • On secure.com

      • Retrieve the unique_number from the URL
      • Create a secure_cookie id
      • Store in the database {cat_cookie_id, unique_number, secure_cookie_id}
      • Delete the unique_number as it is a one-time use key

Now, the database can establish the mapping between cat_cookie_id and secure_cookie_id, facilitating seamless communication between catalog.org and secure.com.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unraveling the Mystery of @Input and @Output Aliases in Angular 2

After researching about the @Input() and @Output() decorators, I discovered that we have the option to use an alias instead of the property name for these decorators. For example: class ProductImage { //Aliased @Input('myProduct') pro ...

When utilizing the multipart/form-data content type in a form, the files being sent are transmitted as blank

I am currently developing a VueJS component that functions as a form to collect user information and enable multiple image uploads. The form is set with enctype="multipart/form-data" and exhibits the following structure : <template> <div> ...

What is the most effective way to send URL strings to the server-side click handler in a jQuery loop using $.each method?

As I work with URL values in my client-side script, I aim to generate links that can transmit these URL values back to my server-side click handler upon clicking. The server-side code /logclick logs the timestamp and destination of the click for auditing p ...

What is the best way to eliminate an item from an array in JavaScript or AngularJS?

I'm attempting to eliminate objects from an array and retrieve the resulting array. I've been using a remove function, but it's not functioning as expected. Here is the input I'm working with: The goal is to remove all values in the ar ...

Vue router beforeRouteEnter - when the page is refreshed, the button label vanishes

<script> export default { name: 'TEST', data() { return { prevRoute: '' } }, methods: { goBack() { return this.$router.go(-1); }, }, beforeRouteEnter(to, from, next) { next(vm => { ...

Enabling Bootstrap modal windows to seamlessly populate with AJAX content

I'm currently in the process of crafting a bootstrap modal that displays the outcome of an AJAX request. Below is my bootstrap code: {{--Bootstrap modal--}} <div id="exampleModal" class="modal" tabindex="-1" role="dialog"> <div class="m ...

Implement an if else statement for handling the Ajax response

Unable to redirect to a different page based on my response. I have attempted the solutions mentioned here, but none of them seem to be working with my Ajax script provided below. success: function (response) { if (response === 'success' ...

How can you securely transfer the ARRAY OBJECT from JavaScript to PHP using Ajax?

I am attempting to send a Javascript Array Object via Ajax to PHP and then use that object as a true Array on the PHP side. My current approach has not been successful in terms of utilizing the incoming object as an Array within PHP; I can only parse it as ...

Exploring JavaScript capabilities with Google - managing and updating object names with numbers

After importing JSON data into Google Scripts, I am able to access various objects using the code snippet below: var doc = Utilities.jsonParse(txt); For most objects, I can easily retrieve specific properties like this... var date = doc.data1.dateTime; ...

ERROR: Running out of memory in JavaScript heap while executing a command with "npm"

Encountered a fatal error (FATAL ERROR: MarkCompactCollector: semi-space copy, fallback in old gen Allocation failed - JavaScript heap out of memory) while attempting to execute any npm command. The error persists even with the simple "npm -v" command. I ...

Switching the checkbox value upon clicking a div element

One challenge I am facing is with a checkbox that saves its value and title in the local storage when clicked. This checkbox is located within a div, and I want the checkbox value to change whenever any part of the div is clicked. Despite my efforts, I hav ...

The script ceased functioning immediately following the inclusion of a case-insensitive search feature and interactive images

In the process of creating my inaugural project featuring a collection of images, I wanted to include a filter/search bar at the top. This bar would dynamically filter the displayed pictures based on user input. For example, typing "Aatrox" into the search ...

Utilizing Grunt to streamline a personalized project

I have set up Grunt as my "JS Task Runner". Node.js is installed in the directory "C:/Program Files". NPM has been installed in C:/users/Peterson/appdata/roaming/npm. Inside the npm folder, I have Grunt, Bower, and Grunt-cli. I am working on a pro ...

When using `parseInt` on the string "802.11 auth", the result did not match my expectations

I am developing a data parser that transforms the output of a command into a JSON object for sending to a live logging and graphing platform. All data extracted by the parser is returned as strings, but I need numerical values to be preserved as numbers. H ...

A platform for creating ER and flow diagrams specifically tailored for web applications, utilizing open source software

Our team is currently working on creating a web application that enables users to create diagrams, such as flow or ER diagrams. We are looking for ways to convert these diagrams into XML or other formats for representation. Are there any open-source soft ...

What is the best way to save a jQuery or JavaScript variable into a JSON file?

Is there a way to save a jquery variable in a json file? I have the following: var image='/test/test.png'; I am obtaining this path through file upload: <input type="file" name="imageurl" value="imagefile"></input> Therefore, I ne ...

Issue with saving cookie from Express.js backend to Nuxt.js frontend

After successfully creating an authorization server using Express.js, I encountered a problem when trying to save the access and rotating refresh tokens as signed cookies. The issue arose from having separate backend and frontend servers with different dom ...

Update MYSQL table values using AJAX and jQuery, then dynamically refresh the updated values on the web page

Hey there! I am fairly new to utilizing ajax and encountering some difficulty with a fundamental concept. In my MySQL table called "users," I have various user information stored, including the balance they pledge to donate. My goal is to create a div elem ...

Is there a way to load JSON data into charts through an AJAX request?

Is there a way to pass JSON data to a JSP file and populate it into the charts data directly without setting each value using a model attribute? In my EmployeeController, I have a lineBarChart method that currently sets data values individually. Here' ...

Stop the page from scrolling when scrolling within a specific DIV to address the [Violation] warning appearing in the console

Initially, it may seem like a duplicate question that has been answered here, but there are additional aspects that need to be addressed. How do I resolve the following [Violation] warning in the Google Chrome console? [Violation] Added non-passive eve ...