GithubHelp home page GithubHelp logo

contently / xdomain-cookies Goto Github PK

View Code? Open in Web Editor NEW
162.0 162.0 51.0 59 KB

A JS lib that provides a mechanism to get/set cookies that can be shared across domains

HTML 28.23% JavaScript 61.29% CSS 10.48%

xdomain-cookies's Introduction

Cross-Domain Cookie Library

This library is intended for cases where you have scripts running on different domains (i.e. domain-a.com, domain-b.com) that need to be able to set/share a cookie value across those domains. A few example use cases would be a third-party script that wants to set/share a user identifier across both domains, or a company that wants to track if a user signed up for a newsletter across both their main website and blog that resides on a different TLD. This library also offers a way of writing data to a cookie from a third-party script

The library leverages 2 files to achieve this - a javascript file you load/run on the page, and an HTML file that gets loaded onto that same page in an iframe by the JS file. The JS & HTML files both must be served from the same domain/location (such as an s3 bucket). The cookies are pushed to the iframe (via postMessage), written as first-party cookies (and localstorage if available) on the remote trusted domain, and are made available for reading/writing locally via a convenient API.

Authored by Authored by Evan Carothers @ Contently

Read the backstory and implementation details on the Building Contently Blog entry Tracking people across multiple domains — when cookies just aren’t enough

Usage

Simply include the script on any page where it's needed, create a new instance of xDomainCookie, and leverage the get/set functions:

<script src="//my.s3bucket.com/xdomain_cookie.min.js"></script>
<script>
	var xd_cookie = xDomainCookie( '//my.s3bucket.com' );
	xd_cookie.get( 'cookie_name', function(cookie_val){
		//cookie val will contain value of cookie as fetched from local val (if present) else from iframe (if set), else null
		if(!cookie_val){
			var new_val = get_what_value_should_be();
			xd_cookie.set( 'cookie_name', new_val );
		}
	});
</script>

Usage Notes

Please Note that it's important for the xdomain_cookie.min.js file to be served from the same domain and protocol as the path passed in for the iframe creation (when creating xDomainCookie). You can setup the script to use whichever page the protocol of the main window is using by specifying // as the protocol prefix (instead of explicit https:// or http://, assuming the webserver hosting the xdomain_cookie.html file supports that protocol). It's also OK to serve both the script and iframe path over HTTPS in all instances, regardless of if the main page is loaded over HTTPS.

This script should work in all modern desktop and mobile browsers that support the postMessage API (IE 8+, Chrome, FF, etc).

Limitations

Due to how browsers handle, and what they consider 3rd-party cookies/data, if a browser is set to disable 3rd-party cookies this library will not function. This is because, regardless of the actual site the cookie is being set on, the top-level source domain must match the domain of internal frames for cookies to be considered 1st-party. Browsers do this for security concerns, and there is unfortunately no way around this based on current browser functionality.

API

xDomainCookie( iframe_domain, namespace, xdomain_only, iframe_load_timeout_ms, secure_only )

Create a new instance of the xDomainIframe object that creates the iframe in the page and is ready for usage

iframe_domain (string, required) the domain, and optional path, where the iframe html script should be loaded from - NOTE should match the protocol/host/port of where the JS script is loaded from

namespace (string,optional) a namespace to use for postMessage passing - prevents collission if you are running multiple instances of this lib on the page... usually not needed

xdomain_only (boolean, optional, default false) if the cookie should only be set on the xdomain site, not locally.. meaning that the xdomain version acts as the source of truth for the cookie value and eliminates local caching. PLEASE NOTE that this flag can provide specific intended behavior for different use cases. See the Cross Domain ONLY Cookies section further down the readme for more info

iframe_load_timeout_ms (integer, optional, default 6000) The number of milliseconds to wait for the iframe to load before assuming a timeout and failing

secure_only (boolean, optional, default false)_ Should the cookies (both remote and local) be set as HTTPS-only secure cookies. Please note that if if this is set to true, the xdomain cookie functionality will NOT function if the page AND the xdomain iframe are not both loaded over https://

//create instance of xDomainIframe with local cookie caching
var xd_cookie = xDomainCookie( "//my.trusted-site.com", "my.namespace" );

//create instance of xDomainIframe that uses xdomain_only cookies
var xd_cookie = xDomainCookie( "//my.trusted-site.com", "my.namespace", true );

//create instance of xDomainIframe that uses secure cookies, with a load timeout of 10 seconds
var xd_cookie = xDomainCookie( "https://my.trusted-site.com", "my.namespace", false, 10000, true );

.set( cookie_name, cookie_value, expires_days )

Set the value of the xdomain (& local) cookie

cookie_name (string, required) the name of the cookie (both for local domain & iframe domain)

cookie_value (string/int/float/obj, required) the value of the cookie that we wish to set, get's JSON encoded & serialized

expires_days (int, optional) # of days to use for setting cookie expiration (default is 30)

my_xdc_instance.set( 'my_cookie', JSON.stringify({foo:"bar"}), 15 );

.get( cookie_name, callback, expires_days )

Get the value of the xdomain (& local) cookie with complete callback. NOTE: this function also re-ups the xdomain cookie as if it was being re-set with .set()

cookie_name (string, required) the name of the cookie (both for local domain & iframe domain)

callback (function, required) function that is called upon retreival of iframe cookie - takes 1 arg, which is the cookie value (if present)

expires_days (int, optional) # of days to use for setting/re-upping cookie expiration (default is 30)

my_xdc_instance.get( 'my_cookie', function( val ){
	  console.log("Current value of xdomain cookie 'my_cookie'", val );
});

Cross Domain ONLY Cookies

By default the xDomainCookies class is configured to set and use a local cookie as a caching mechanism to allow the callback for .get() to return as fast as possible. This is based on the fact that you are setting a piece of information that should not change on any domains you are using the xDomainCookie on, as if you change the cookie from a single domain and it's cached locally at another domain, that local cache will prevent the updated value from being returned by the get() callback on that specific domain.

For use cases where you are setting a cookie value that should not change (such as something simple like a user ID), allowing the local cookie cache to function is useful and ideal. If, however, you are using advanced data types (such as a serialzed JSON object that has a property that can be updated from multiple domains, and needs to always have the most updated values accessible), then you should pass in true for the xdomain_only param when creating a new xDomainIframe instance. This means that the local cookie cache isn't used, and the iframe must fully lead before the callback to get() will fire, but will guarantee that any interaction with the cookie data will always use up-to-date values.

Testing

There's a full test suite that leverages zombie/connect to mock & test the library behavior across multiple domains in multiple different situations. There is also a pre-build development setup to load/test in local environments in the library. Both of these rely on npm packages, so be sure to do an npm install in the root dir before running.

Test suite
npm test
Dev Server & Development

The dev server runs on localhost:3001. Once running you can map whatever hosts to 127.0.0.1 and load the JS in running local pages from {{myhost}}:3001/xdomain_cookie.dev.js.

npm run dev

It is also pre-configurd with an example scenario that shows usage across domains. It requires you to map the following domains to 127.0.0.1 in your hosts file: shared_cookie_test.com, shared_cookie_test2.com, and shared_cookie_iframe.com

You can then see the example working by visiting http://shared_cookie_test.com:3001/test_page.html and shared_cookie_test2.com/test_page.html - take a look at the console output to see cookie behavior.

Additinoally to test SSL/secure cookie functionality, a self-signed cert is included for shared_cookie_test.com and you can verify by visiting https://shared_cookie_test.com:3002/test_page.html (which uses shared_cookie_iframe.com:3003 as an iframe host with another self-signed cert). Please note your browser may deem these as insecure at first, so you will need to click to approve them as trusted in your browser.

When developing locally you can lint/test/build the library by running gulp build

xdomain-cookies's People

Contributors

ecaroth avatar lorgio avatar saaqibz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xdomain-cookies's Issues

error in checking types

error:

xdomain_cookie.js:47 Uncaught TypeError: Cannot use 'in' operator to search for 'msg_type' in null
    at _inbound_postmessage (xdomain_cookie.js:47:30)

problem is here:

            if (typeof event.data !== 'string') return; //expected json string encoded payload
            var data = null;
            try {
                data = JSON.parse(event.data);
            } catch (e) {
            }

            if (typeof data !== 'object' || (data instanceof Array)) return; //data is not a non-array object
            if (!('msg_type' in data) || data.msg_type !== 'xdsc_read') return; //data is not a xdomainc-cookie payload
            if (!('namespace' in data) || data.namespace !== _namespace) return; //wrong namespace for msg

if JSON.parse(event.data) fails (for example, if event.data = 'lorem ipsum';, then in data const is still null. But if this condition:
typeof data !== 'object' is wrong, because typeof null === 'object'. easy fix:
add new condition:

if (data === null) return

location.hash var error

JSON.parse needs a value otherwise it dies and kills the script.

Uncaught SyntaxError: Unexpected end of JSON input
at JSON.parse ()
at xdomain_cookie.html:8

Simple solution:

var _hash_data = '';
if(window.location.hash.substr(1)){
  _hash_data = JSON.parse(decodeURIComponent(window.location.hash.substr(1)));
}

Does this library still work in 2021

Safari is blocking all 3rd party cookies.. and Google is following something similar.

Only way i can think of is wrapping JS inside a subdomain via cname.

Ie... serving.com/pixel.js lives on customersite.com

So customer creates "serving.customersite.com" cname, and points it to serving.com

Now "serving.customersite.com/pixel.js" is not considered 3rd party.

Am I correct on this assumption?

License

Hi,
can you please set the license of the project?

Thanks

Update cookie data from one website, get the updated data on the other website

I did the set up yesterday and it works fine. I'm now sharing user data between websites, which is absolutely amazing :) Kudos to @ecaroth!

There is still something I didn't succeed to achieve. My first use case is about sharing data between an online store and its knowledge base. This way, we can see which customers are actually using the knowledge base. It works well but sometimes, customer data would be updated on the online store. Here is the data I'm writing in the cookie:

<script type="text/javascript" src="//app.helpman.io/xdomain_cookie.js"></script>
<script type="text/javascript">
    var helpman_cookie = xDomainCookie('//app.helpman.io');
    var customer_data = {
      "distinct_id": "{{ customer.id }}",
      "name": "{{ customer.name }}",
      "email": "{{ customer.email }}",
      "custom_fields": {
        "lifetime_spent": "{{ customer.lifetime_spent }}",
        "last_order": "{{ customer.last_order.created_at }}",
        "tags": "{% for tag in customer.tags %}{{ tag }} {% endfor %}"
      }
    };
    helpman_cookie.set('helpman_petitkiwi', JSON.stringify(customer_data));
</script>

I'm interested to share key data about each customer, that's what I put in custom_fields. This data will be updated regularly.

But actually the cookie data is not shown as updated on the knowledge base side. I suspect local storage to be the culprit, but I don't see the cookie stored locally using the Chrome development tools.

Any idea?

publish on npm

So far I found no released version or module with the name xdomain-cookies on npmjs.

Vulnerabilities Found

git clone ...
npm install

added 521 packages from 916 contributors and audited 2027 packages in 15.095s
found 13 vulnerabilities (4 low, 1 moderate, 6 high, 2 critical)

npm audit fix
fixed 0 of 13 vulnerabilities in 2027 scanned packages
4 package updates for 13 vulns involved breaking changes
(use npm audit fix --force to install breaking changes; or refer to npm audit for steps to fix these manually)

Run/build/test fails on Node > 6

Nothing anywhere indicates that this requires Node 6 or below to run/build/test. This is likely why #18 is failing as the default version on Semaphore is 8.11.

Intelligent Tracking Prevention

As you might be aware that Apple recently published a change to Safari that would affect this library. See this official Apple announcement for more details

I say it'd affect this library because you set a third-party cookie and then read from this cookie using an iframe to keep this id unique and consistent. Safari would make this cookie unavailable after 24 hours of setting it. So any user who visits the page using Safari with a gap of more than 24 hours would give us a different ID.

How do you plan to address it?

Using the libraries

Hello guys, I'm kind of new in this universe of cookies and I found your library searching how to create and read cross domain cookies.

I'm a little bit confusing about how to use the library. On the README.md, it's not clear to me if I need to host the javascript AND the xdomain_cookie.html at the server that I need to centralize the cookies.

Working with in-browser disabled third-party cookies

Hi.

I'm a newbie with your library. The readme says it should work even if user disabled third-party cookies in the browser. I'm trying to re-create that with the example provided in the repository. So I run npm run dev, make sure third-party cookies are disabled, navigate to http://shared_cookie_test.com:3001/test_page.html in one tab and then to http://shared_cookie_test2.com:3001/test_page.html in another.
The console on the first page outputs

test_page.html:39 COOKIE VAL RETURN:  null
test_page.html:45 SETTING EMPTY COOKIE set_from:shared_cookie_test.com:3001
test_page.html:52 COOKIE VAL RETURN AFTER SET: set_from:shared_cookie_test.com:3001

The console on the second page outputs

COOKIE VAL RETURN:  null
test_page.html:45 SETTING EMPTY COOKIE set_from:shared_cookie_test2.com:3001
test_page.html:52 COOKIE VAL RETURN AFTER SET: set_from:shared_cookie_test2.com:3001

After reloading the console on the first page ouputs

test_page.html:39 COOKIE VAL RETURN:  set_from:shared_cookie_test.com:3001

and on the second

test_page.html:39 COOKIE VAL RETURN:  set_from:shared_cookie_test2.com:3001

I guess that should not happen. Browser - Chrome 53.0.2785.116, OS - Windows 8.1 Pro x64.

License

Do you have plans to expose this repository under some open source license ?

Change Path and Domain of the Cookie

Hello, first of all thank you for developing this library and helping us with this issue.

I'm currently setting and getting the cookie without any technical problems, but the cookie is setted with the path '/trackercookie' (where it's hosted) and the domain is being setted to 'api.qas.impresa.pt'. But I need it to be setted with the path '/' and the domain to '.impresa.pt', because I want this cookie to be sent to the micro services hosted at api.impresa.pt and id.impresa.pt.

I tried to change the method _set_local_cookie, adding 'path=/' to the string at line 109, but it didn't work for me.

Is it possible to manipulate this values inside xdomain_cookie.html?

Doesn't work in chrome anymore after february 2020

Please check
https://digiday.com/media/what-is-chrome-samesite/

Check an example for the errors

What is the change?

Google first announced in May last year that cookies that do not include the “SameSite=None” and “Secure” labels won’t be accessible by third parties, such as ad tech companies, in Chrome version 80 and beyond. The Secure label means cookies need to be set and read via HTTPS connections.

Right now, the Chrome SameSite cookie default is: “None,” which allows third-party cookies to track users across sites. But from February, cookies will default into “SameSite=Lax,” which means cookies are only set when the domain in the URL of the browser matches the domain of the cookie — a first-party cookie.

Any cookie with the “SameSite=None” label must also have a secure flag, meaning it will only be created and sent through requests made over HTTPs. Meanwhile, the “SameSite=Strict” designation restricts cross-site sharing altogether, even between different domains that are owned by the same publisher.

Mozilla’s Firefox and Microsoft’s Edge say they will also adopt the SameSite=Lax default.

Why is Google making this update?

Third-party cookies can make people vulnerable to malicious tracking, data leakage and can also make them susceptible to what are known as cross-site request forgery attacks. A user might click on a nefarious link in an email that allows a bad actor the ability to log into their banking website, for example.

“In order to move the web ecosystem to a more healthy place, we are changing the default behavior for when SameSite is not specified to automatically default to a more secure option rather than a less secure option,” said a Google spokesperson.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.