Enabling / Disabling All Cookies Upon User Consent for GDPR - javascript

This issue is related to GDPR compliance but I'll keep it more focused on the technical issue at hand:
I have found some great open source resources for cookie consent banners, like Cookie Consent and Cookie Script. The implementation of the banner looks simple enough. The issue though is they require cookies to be disabled by default, which I am unsure how to do on a global level on a domain.
I don't know a lot of JavaScript but what I'm wondering is: Is there a method with Javascript to universally allow or deny cookies on a domain? Or, would this method be unique to each script in question? Google Analytics for example has documentation on disabling cookies. How would I lump that together with Facebook, Youtube, and all the other scripts using cookies and only allow cookies after a user has consented? Or, would I have to address it for each individual script?
In other words, is there a method in JavaScript where I can universally turn off/on cookies depending on user preference? Just from my research so far it seems there is not.

I have created a Proxy script on the document.cookie variable.
Run this script as the first script in your document.
Note
This solution assumes:
Cookies are set through javascript (and server side uses sessions).
It also only works on browsers which support the use of javascript proxies.
It only works for local domains (it only prevents external domain cookies from being set)
The Proxy script
Setting a cookie
What it does it that it intercepts the document.cookie variable because window.disableCookies is set to true in the script below. It stores the cookies in the window.cookieList array until the enableCookies script is executed. If enableCookies is executed, it will disable the proxy and iterate over the window.cookieList variable, to set the cookies in the browser.
Reading the cookies
If a script sets a cookie it expects the cookie in the document.cookie variable. So until the enableCookies function is called (and window.disableCookies is set to false), it fakes a document.cookie response, it builds it based upon the window.cookieList variable.
var cookie_setter_orig = document.__lookupSetter__("cookie").bind(document);
var cookie_getter_orig = document.__lookupGetter__("cookie").bind(document);
window.cookieList = [];
window.disableCookies = true;
Object.defineProperty(document, "cookie", {
get: function () {
if(!window.disableCookies) {
return cookie_getter_orig();
} else {
var response = "";
window.cookieList.forEach(function(cookie){
var splitted = cookie.split(";")[0].split("=");
response += splitted[0] + "=" + splitted[1] + "; ";
});
return response.slice(0, response.length - 2);
}
},
set: function (val) {
if(!window.disableCookies) {
cookie_setter_orig(val);
} else {
window.cookieList.push(val);
}
}
});
function enableCookies()
{
window.disableCookies = false;
window.cookieList.forEach(function(cookie){
document.cookie = cookie;
});
window.cookieList =[];
}
Testing it out
To test it out you can execute the following script:
/* These cookies are not set; they are set on the window.cookieList, until enableCookies is activated */
document.cookie = 'cookie1=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
document.cookie = 'cookie2=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
document.cookie = 'cookie3=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
/* This is a fake cookie list from the window.cookieList variable
* Output: cookie1=test; cookie2=test; cookie3=test
*/
console.log(document.cookie);
setTimeout(function(){
enableCookies(); /* Enable cookies and pass them to the browser */
/* The cookie below is passed to the browser directly, since cookies are enabled */
document.cookie = 'cookie4=test; expires=Sun, 1 Jan 2023 00:00:00 UTC; path=/';
/* This is the real cookie list
* Output: cookie1=test; cookie2=test; cookie3=test; cookie4=test
*/
console.log(document.cookie);
}, 2500);

Is there a method with Javascript to universally allow or deny cookies on a domain?
No.

Related

My cookie doesn't persist between sessions?

I have a cookie that saves some fairly benign data I use to check if a Changelog modal window should appear on a page or not. When I load a page there is no cookie at all. The project runs on IIS, using .NET Core 2.2 with ASP and MVC. So I do the following:
function showChangelog(override = false) {
let newestEntryId = getNewestChangelogVersion();
let cookieEntryId = getCookieChangelogVersion();
if (newestEntryId > cookieEntryId) {
setCookieDetails(false, newestEntryId);
cookieEntryId = newestEntryId;
}
let changelogPersistence = getCookieChangelogPersistence();
if (changelogPersistence === false || override === true) {
let modalBody = $('#changelogModalBody');
...
...
Here is what happens:
The first check returns 0. As it should. That is the newest entry in the changelog object.
The second check returns -1. As it should. There is no cookie to check at this stage, so I return -1 to indicate this.
Then I see if the newest entry gathered from the changelog is higher than the one from the cookie. If it is, override it and write the new version number to the cookie. That produces the following cookie:
"dontPersistChangelog=false; changelogVersion=0; path=/; expires=Tue, 06 Sep 2022 13:54:33 GMT"
Then, from this new cookie I check whether the cookies persistence flag is true or false. If it is true, then don't show the window. If it is false, then do show the window.
Then the code goes on to just make the window appear with all the relevant information. Sounds good.
For good measure, here is the code that sets the cookie:
/**
* Used to set the website cookie for the changelog window.
* #param {boolean} persistence Whether the changelog should not persist (true) or persist (false)
* #param {number} version What version of the log is being put in the cookie.
*/
function setCookieDetails(persistence, version) {
let expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + 999);
let persistChangeLog = 'dontPersistChangelog=' + persistence;
let changelogVersion = 'changelogVersion=' + version;
document.cookie = persistChangeLog;
document.cookie = changelogVersion;
document.cookie = 'path =/';
document.cookie = 'expires=' + expirationDate.toUTCString();
}
Here is the puzzling part; The actual cookie seizes to exist when I close the browser and start the browser back up. I checked using the console in the browser. It's like it gets deleted and its gone. I was under the impression that document.cookie was not the same as a session cookie? That it could persist through separate sessions?
I tried the cookie with and without an expiration date. The cookie is deleted either way. This both happens when I run the project in Visual Studio or the deployed version on my IIS.
What am I potentially doing wrong?
See https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
I don't think your calls to document.cookie are updating properties of an existing cookie. A cookie's properties are semicolon separated and stored as a string.
So you set up a cookie like so:
function resetOnce() {
document.cookie = "doSomethingOnlyOnce=; expires=Thu,01 Jan 2050 00:00:00 GMT";
}
So for your function above:
function setCookieDetails(persistence, version) {
let expirationDate = new Date();
expirationDate.setDate(expirationDate.getDate() + 999);
let persistChangeLog = 'dontPersistChangelog=' + persistence;
let changelogVersion = 'changelogVersion=' + version;
document.cookie = persistChangeLog + ";path =/;expires=" + expirationDate.toUTCString();
document.cookie = changelogVersion + ";path =/;expires=" + expirationDate.toUTCString();}

Deleting duplicate JavaScript cookies based on the scope of domain and name

I recently changed the scope of some JavaScript cookies on our site. They were all scoped to the subdomain in which they were created. They are now scoped globally to the domain. The issue is I now have duplicate cookies that have different scopes.Is it possible to programatically eliminate the JavaScript cookies based on name and scope (domain)? Example:
cookieA --> domain=.mysite.com
cookieA--> domain=sub.mysite.com
cookieB --> domain=.mysite.com
cookieB --> domain=sub.mysite.com
I want to remove only cookies with domain = sub.mysite.com by name.
You can do this using JavaScript Cookie library.
If you want delete cookie named cookieA, which is set do domain sub.mysite.com, just run:
Cookies.remove("cookieA", {domain: "sub.mysite.com"})
This will remove sub.mysite.com's cookieA, and leave .mysite.com's cookieA untouched.
If you don't want to use this library, you can do it directly:
document.cookie = "cookieA=;domain=sub.mysite.com;expires=Thu, 01 Jan 1970 00:00:01 GMT"
We had the same problem when changing our cookies to a global domain. Quite a lot of functionality was affected because duplicate cookies now exist (ex: www.domain.com and .domain.com). Since we deploy our website to different domains (dev, acc, prod) these issues were spread out across different domains.
Without going through all the pages to find issues cross domain, we've come up with a solution that doesn't require to know all the cookie names:
/*
* #param c: window.Cookies
* #doc https://github.com/js-cookie/js-cookie
*/
(function(c) {
var arrCookies = document.cookie.split(/; */);
var arrCookie;
for (var cookie in arrCookies) {
if (arrCookies.hasOwnProperty(cookie)) {
arrCookie = arrCookies[cookie].split('=');
c.remove(arrCookie[0], { domain: window.location.hostname });
console.log('removing cookie ' + arrCookie[0] + ' on: ' + window.location.hostname);
}
}
}(window.Cookies));
This solution cleans up the active domain by using window.location.hostname and re-enables functionality for your previously set subdomain.

Why would setting document.cookie not work in Chrome?

My coworker ran into an issue where NO cookie could be set on Chrome via code like this:
document.cookie = "TEST=1; expires=Tue, 14 Oct 2014 20:23:32 GMT; path=/"
Putting document.cookie into the console immediately after would show results as if I made no change. On refresh of the page, the cookie was not there so it was reporting correctly, just not setting correctly.
The above code would work if he opened a new incognito window and worked for everyone else in general. I removed all his cookies using the dev tools and still had no luck manually setting cookies ( although others would come back that were set via the server headers).
Once he restarted Chrome, it started to behave properly, so it seems like he was running up against some quirk or bug that can no longer be reproduced.
Has anyone else run into this? As of now I am thinking of checking that document.cookie reports back what is expected after setting, and then initiating our cookieless flow for when a user has cookies disabled when things don't match up. I hate the idea of doing that so any suggestions / answers would be great.
The way cookies work, at least in Chrome, is a bit weird.
If you need to change a cookie's value, then you need to add/set each keys one by one.
Try this in your console:
document.cookie; // -> "expires=Tue, 14 Oct 2014 20:23:32 GMT; path=/"
document.cookie = 'TEST=1';
document.cookie; // -> "TEST=1; expires=Tue, 14 Oct 2014 20:23:32 GMT; path=/"
Yes, it has added the key, and not replaced the whole cookie with TEST=1.
If you need to remove a key, you can simply provide no value: TEST=.
I hope this will get you out of the cookie nightmare (it was for me).
Make sure to run it on a server (at least a local server) so that document.cookie works.
If you locally run this file in the browser. "document.cookie" wouldn't work.
As another user mentioned, you have to set them one-by-one. These functions can be useful in parsing & applying a cookie string:
function clearCookies(){
var cookies = document.cookie.split(';');
for(i in cookies){
var vals = cookies[i].split('=');
var name = vals.shift(0, 1).trim();
document.cookie = name+'=';
}
}
function parseCookies(cookie){
clearCookies();
var cookies = cookie.split(';');
for(i in cookies){
var vals = cookies[i].split('=');
var name = vals.shift(0, 1).trim();
document.cookie = name+'='+vals.join('=');
}
}
You have to set the domain!
function setCookie(cname, cvalue, exdays) {
const d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
let expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;domain=" +
window.location.hostname;
}
The expiry date set for the cookie might be the problem. I have come into a problem like this before on Chrome. Set the date to present or future date and test if it would work. Probably that was how Chrome was designed.
We have the same problem in work a while ago, in our case it only happen when we work in local enviroment, after research we crossed an article that said that browser have some kind of problems with localhost:3000, because it recognizes as an insecure page or something like that.
We fixed just by replacing localhost:3000 for 127.0.0.1:3000 (i think that the ip depends on your configuration), and after we replaced that it works perfectly. I hope it helps you.

Cookie not getting deleted

In my asp.net application, am creating a cookie from server side using following code
Dim aCookie As New HttpCookie("StartDownload")
aCookie.Value = "True"
aCookie.Expires = DateTime.Now.AddMinutes(1)
Response.Cookies.Add(aCookie)
When I execute this code, the cookie is getting created, but am not able to delete the cookie from javascript on click of a button. Below is the javascript code.
function delCookie() {
alert(document.cookie);
document.cookie = "StartDownload" + "=; expires=" + new Date(0).toUTCString();
alert(document.cookie);
}
Am using IE browser. Not sure what the problem is. Kindly help.
You can try to hardcode the expiry date, something like, Thu, 01-Jan-1970 00:00:01 GMT and see if that'd work for you or not.
If still not, you might want to ask yourself following questions:
Have you checked the client-side and server-side cookie domains and paths to ensure they're the same?
Is one cookie secure and the other not?
Are there any server/client clock sync issues?

Setting persistent cookies with javascript

I have found a weird bug in my application and due to my small experience with Javascript I couldn't debug it;
I am trying to set a persistent cookie, which will die after one year from its set (max value in major browsers) but persists and won't be deleted after the browser gets closed. I've been using this code:
// Build the expiration date string:
var expiration_date = new Date();
expiration_date.setYear (expiration_date.getYear () + 1);
expiration_date = expiration_date.toGMTString();
// Build the set-cookie string:
var cookie_string = "test_cookies = true; path=/; expires=" + expiration_date;
// Create/update the cookie:
document.cookie = cookie_string;
I've noticed that the cookie has a session tag when I use cookie manager plugin, and only the ones with this tag get removed when the browser shuts down (others like Wordpress's and such scripts persist).
I changed your syntax over to my style of coding (variables at the top, minimal re-casting, etc.) and the example below works on my localhost quite well.
// Build the expiration date string:
var expiration_date = new Date();
var cookie_string = '';
expiration_date.setFullYear(expiration_date.getFullYear() + 1);
// Build the set-cookie string:
cookie_string = "test_cookies=true; path=/; expires=" + expiration_date.toUTCString();
// Create or update the cookie:
document.cookie = cookie_string;
If you are having problems on a production server, try setting the domain of the cookie as well (www.quirksmode.org/js/cookies.html#link5)
You can also use the max-age attribute.
cookie_string = "test_cookies=true; path=/; max-age=31536000";
One week: max-age=604800
One month: max-age=2628000
One year: max-age=31536000
have you tried using the getFullYear() and setFullYear() methods of the Date instance instead of getYear() and setYear() ? the latter are are deprecated, see here.
hope that helps! cheers.

Categories

Resources