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

Is there a way to navigate to a specific div when clicking on it?

Need help with scrolling after running code function scrollFunction() { document.getElementById('insert').scrollIntoView(); } I have a button that triggers some code and I want the page to scroll afterwards. Currently, it scroll ...

Issue with ExpressJS Regex not correctly matching a path

I'm currently struggling with a simple regex that is supposed to match words consisting of letters (0-5) only, but for some reason it's not working as expected. Can anyone help me figure out the correct expression and how to implement it in Expre ...

Introducing the innovative Icon Collapsable JQuery - a versatile tool that

I'm looking to set custom icons for the JQuery Collapsable view without having to make changes to the default JQuery CSS and .JS files. You can take a look at my starting point on jsFiddle here: http://jsfiddle.net/jakechasan/M7LLU/ Although I' ...

Modify section background color for every iteration in an image carousel

Is it possible to dynamically change the background color of the cd-hero section each time a new image is loaded in a simple slider on the home page? Can this be achieved by storing predefined colors in an array so that different images trigger different b ...

JavaScript Array Problem

Could you please review the code below and help me understand why I am encountering issues when trying to run the program? $(document).ready(function() { var comp = new Array("AAPL", "MSFT", "XRTX&"); var t = setInterval(function(){ ...

Issue with variable not being refreshed within requestJS's data event

I have been attempting to store the response from a URL in a variable for caching purposes and then send it upon subsequent requests. I am currently writing to the variable during the data event of the request. The variable does get updated, but I am encou ...

A conflict with the Ajax file is causing an automatic logout

In my Rails application, there is a page with a table that uses partial AJAX to increase the capacity attribute in a time entity. You can view the visual representation of the table here. By clicking the plus/minus button, the capacity attribute increases ...

Using JavaScript to display dynamic data pulled from Django models

I am currently in the process of designing my own personal blog template, but I have encountered a roadblock when it comes to creating a page that displays previews of all posts. This particular page consists of two columns, #content-column-left and #conte ...

The AngularJS modal is sending back the results before updating the parent scope

When launching a modal from my web page, I am updating an array passed from the parent. However, when closing the modal and sending back the updated results, the parent scope object is also being updated. If the user decides not to update and cancels the ...

Jest is simulating a third-party library, yet it is persistently attempting to reach

Here's a function I have: export type SendMessageParameters = { chatInstance?: ChatSession, // ... other parameters ... }; const sendMessageFunction = async ({ chatInstance, // ... other parameters ... }: SendMessageParameters): Promise<vo ...

Angular.js Form Submission Results in Error 405: POST Method is Not Permitted

Every time I attempt to submit my form, I come across a 405 error. Here is the code snippet from my controller: 'use strict'; angular. module('myApp'). component('zipPopup', { templateUrl: 'zip-popup/zip ...

What steps do I need to take to link my form with Ajax and successfully submit it?

Here is my HTML code: {% extends 'base.html' %} {% block content %} <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Create a Recipe ...

Creating a line of functions pool in Javascript with a delay feature

Recently, I created a code snippet that simulates a function line. It involves calling functions such as fn1, delay, fn2, delay, and so on. The idea is to call a function, remove it from the line, have a short sleep, and repeat. However, I've encount ...

Implementing dynamic webpage updates based on dropdown list selections

In my webpage, I am displaying a list of movies fetched from an API. The issue I am facing is related to sorting the movies based on user selection. When I uncomment one of the sort methods in my code, it works as intended. What I want to achieve is that ...

Convert XML to an HTML table in real-time as new elements are introduced

Currently, I have JSON and AJAX code that fetches XML data every second, which is working smoothly. When I added an XML element, it automatically gets added to an HTML table. The issue arises when I call the function every 3 seconds; the page refreshes due ...

Implementing SVG in NextJS 13 with custom app directory: A step-by-step guide

Recently, I decided to explore the app directory and unfortunately ran into some issues. One of the main problems I encountered was with image imports. While PNG images imported without any problem, SVG images seemed to break when importing in /app. For i ...

dynamic search suggestions powered by ajax

Developing a search module with Auto Suggest functionality for ASP.Net. The search criteria is Training Name, and the database contains up to 30,000 trainings. Selecting an approach that ensures optimal performance is crucial due to the large size of the t ...

Unable to see the array values in jquery autocomplete

Hey there, I'm currently using jQuery autocomplete with CodeIgniter. My result array is fetched from the database and I am sending it back as JSON-encoded data. However, I am facing an issue where the values in the search results are not being display ...

An issue arises with the Datatables destroy function

Utilizing datatables.js to generate a report table on my page with filters. However, when applying any of the filters, the data returned has varying column counts which prompts me to destroy and recreate the table. Unfortunately, an error message pops up ...

Issue with integrating Google Spreadsheet as the data source for a Next.JS website: updates are not reflecting on the website pages

The website for this restaurant was created by me, using Google Spreadsheet to populate the menu pages. I chose this method for its simplicity and familiarity to the client. I'm utilizing the google-spreadsheet package to extract necessary informatio ...